<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
	<External>null</External>
	<External>nil</External>
	<Item class="Folder" referent="RBX9aeb48614c0447d9b3ff5f8d043013d6">
		<Properties>
			<Color3 name="IconTint">
				<R>0</R>
				<G>0</G>
				<B>0</B>
			</Color3>
			<BinaryString name="AttributesSerialize"></BinaryString>
			<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
			<bool name="DefinesCapabilities">false</bool>
			<string name="Name">Vibe Coder</string>
			<int64 name="SourceAssetId">-1</int64>
			<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
		</Properties>
		<Item class="ModuleScript" referent="RBXa279b42bfb6a4be18c110f5b0f660b97">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local module = {}
local WidgetModelSelectFrameOpener = require(script.Parent.WidgetModelSelectFrameOpener)
local ModelRegistry = require(script.Parent.ModelRegistry)
local AISendHandler = require(script.Parent.AISendHandler)
local GamepassHandler = require(script.Parent.GamepassHandler)
local ComposerControls = require(script.Parent.App.ComposerControls)
local DiffReviewUI = require(script.Parent.App.DiffReviewUI)

local UserInputService = game:GetService("UserInputService")
local lastText = ""

local EYE_SLASH_ID = "rbxassetid://73515595170574"
local EYE_OPEN_ID = "rbxassetid://111941355414985"

local widget_info = DockWidgetPluginGuiInfo.new(
	Enum.InitialDockState.Right, -- Start docked to the right
	false, -- Initially enabled
	false, -- Don't override the previous state
	470, -- Default width
	800, -- Default height
	380, -- Minimum width
	300 -- Minimum height
)

local function model_label(v)
	return v.display_name or v.name
end

function module.build_model_selection(pd)
	for i, v in ipairs(ModelRegistry) do
		local clonned_model_select_button = pd.widget.App.ModelSelectFrame.ModelsList.ModelSelectButton:Clone()
		clonned_model_select_button.Visible = true
		clonned_model_select_button.Text = model_label(v)
		clonned_model_select_button.Parent = pd.widget.App.ModelSelectFrame.ModelsList
		clonned_model_select_button.MouseButton1Click:Connect(function()
			-- Free tier may use Auto; other models stay PRO
			if not GamepassHandler.get_gamepass_ownership() and not v.is_auto then
				pd.widget.App.ModelSelectFrame.Visible = false
				
				pd.widget.BuyProFrame.Visible = true
				pd.widget.BuyProFrame.Header.Text = "You have discovered a Vibe Coder PRO feature."
				
				return
			end
			
			pd.current_model = v.name
			pd.widget.App.ModelSelectFrame.Visible = false
			pd.widget.App.BottomThread.ApiKeyInput.Text = pd.plugin:GetSetting("vibe-coder-secret-"..(pd.current_model:gsub("[^%w]", ""))) or ""
			pd.plugin:SetSetting("vibe-coder-last-model", pd.current_model)
			module.update_ui(pd)
			if pd.spawn_system_bubble then
				pd.spawn_system_bubble("Model: " .. model_label(v))
			end
		end)
	end
end

function module.update_api_key_visibility(pd)
	pd.widget.App.BottomThread.ApiKeyHiddenLabel.Visible = pd.api_key_hidden
	pd.widget.App.BottomThread.ApiKeyInput.Visible = not pd.api_key_hidden

	if pd.api_key_hidden then
		pd.widget.App.BottomThread.ShowApiKeyButton.Image = EYE_OPEN_ID
	else
		pd.widget.App.BottomThread.ShowApiKeyButton.Image = EYE_SLASH_ID
	end
end

function module.build_widget(pd)
	-- Create the DockWidget
	pd.widget = pd.plugin:CreateDockWidgetPluginGui("VibeCoderWidget", widget_info)
	pd.widget.Title = script.Parent.VersionTitle.Value or "Vibe Coder"
	pd.widget.Enabled = false
	
	if pd.gamepass_ownership then
		pd.widget.Title ..= " PRO"
	end
	
	for i, v in ipairs(script.Parent.Prefabs.WidgetGUI:GetChildren()) do
		local clone = v:Clone()
		clone.Parent = pd.widget
	end
	
	WidgetModelSelectFrameOpener.setup_model_select_frame(pd)
	WidgetModelSelectFrameOpener.setup_menu_frame(pd)
	
	module.build_model_selection(pd)
	ComposerControls.setup(pd)
	DiffReviewUI.setup(pd)
	AISendHandler.attach_session_helpers(pd)

	-- First-open welcome (once per Studio session)
	if not pd._welcomed then
		pd._welcomed = true
		task.defer(function()
			if pd.spawn_system_bubble then
				pd.spawn_system_bubble(
					"Welcome to Vibe Coder v1.1.0 — just chat. Auto edits your place with tools; @mentions add context. Selection is optional."
				)
			end
		end)
	end

	local continueAuto = pd.widget:FindFirstChild("NoSelectionFrame")
		and pd.widget.NoSelectionFrame:FindFirstChild("ContinueAutoButton")
	-- Legacy overlay kept hidden; chat no longer requires script selection.
	if pd.widget:FindFirstChild("NoSelectionFrame") then
		pd.widget.NoSelectionFrame.Visible = false
	end
	if continueAuto then
		continueAuto.MouseButton1Click:Connect(function()
			pd.current_model = "auto"
			pd.plugin:SetSetting("vibe-coder-last-model", "auto")
			pd.widget.App.BottomThread.ApiKeyInput.Text =
				pd.plugin:GetSetting("vibe-coder-secret-auto") or ""
			pd.widget.NoSelectionFrame.Visible = false
			module.update_ui(pd)
			if pd.spawn_system_bubble then
				pd.spawn_system_bubble("Using Auto — no script selection required.")
			end
		end)
	end
	
	pd.widget.App.BottomThread.ApiKeyInput.Text = pd.plugin:GetSetting("vibe-coder-secret-"..(pd.current_model:gsub("[^%w]", ""))) or ""
	
	pd.widget.App.BottomThread.SendButton.MouseButton1Click:Connect(function()
		AISendHandler.on_send_button_click(pd)
	end)
	
	pd.widget.App.BottomThread.ChatInputTextBox:GetPropertyChangedSignal("Text"):Connect(function()
		local box = pd.widget.App.BottomThread.ChatInputTextBox
		local newText = box.Text
		if newText:sub(-1) == "\n" and not lastText:match("\n$") then
			if not (UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)) then
				box.Text = lastText
				AISendHandler.on_send_button_click(pd)
			end
		end
		-- @ autocomplete: newly typed trailing @ expands selected/selection path
		if newText:sub(-1) == "@" and lastText:sub(-1) ~= "@" then
			local target = pd.selected_script
			if not target then
				local sel = game:GetService("Selection"):Get()
				target = sel[1]
			end
			if target and target.Parent then
				local PathUtil = require(script.Parent.Tools.PathUtil)
				local path = PathUtil.getFullName(target):gsub("^game%.", "")
				box.Text = newText .. path
				newText = box.Text
			end
		end
		lastText = newText
	end)
	
	module.update_api_key_visibility(pd)

	pd.widget.App.BottomThread.ApiKeyInput.FocusLost:Connect(function()
		pd.plugin:SetSetting(
			"vibe-coder-secret-" .. (pd.current_model:gsub("[^%w]", "")),
			pd.widget.App.BottomThread.ApiKeyInput.Text
		)
	end)

	pd.widget.App.BottomThread.ShowApiKeyButton.MouseButton1Click:Connect(function()
		pd.api_key_hidden = not pd.api_key_hidden
		pd.plugin:SetSetting("vibe-coder-api-key-hidden", pd.api_key_hidden)
		module.update_api_key_visibility(pd)
	end)
	
	pd.widget.BuyProFrame.CloseButton.MouseButton1Click:Connect(function()
		pd.widget.BuyProFrame.Visible = false
	end)
end

function module.update_ui(pd)
	if not pd.widget then
		return
	end

	-- Chat-first: never block on script selection (Cursor-style).
	if pd.widget:FindFirstChild("NoSelectionFrame") then
		pd.widget.NoSelectionFrame.Visible = false
	end

	local model_data = AISendHandler.get_model_data(pd.current_model)
	local is_auto = model_data and model_data.is_auto

	local titleFrame = pd.widget.App.BottomThread:FindFirstChild("SelectedScriptFrame")
	if titleFrame then
		local hasScript = pd.selected_script ~= nil and pd.selected_script.Parent ~= nil
		titleFrame.Visible = hasScript
		if hasScript and titleFrame:FindFirstChild("ScriptTitle") then
			titleFrame.ScriptTitle.Text = pd.selected_script.Name
		end
	end
	pd.widget.App.BottomThread.CurrentModelButton.ModelTitle.Text = model_label(model_data or { name = pd.current_model })
	
	if pd.model_thinking_frame then
		local frame = pd.model_thinking_frame
		local okThink = pcall(function()
			local time_elapsed = tick() - (pd.model_thinking_started or tick())
			local bubble = frame:FindFirstChild("Bubble")
			if not bubble then
				return
			end
			local timeLabel = bubble:FindFirstChild("TimeLabel")
			local taskLabel = bubble:FindFirstChild("TaskNameLabel")
			if timeLabel then
				timeLabel.Text = string.format("%.1f", time_elapsed).."s"
			end
			if taskLabel then
				taskLabel.Text = "Thinking…"
				if time_elapsed > 7 then
					taskLabel.Text = "Analyzing the problem…"
				end
				if time_elapsed > 15 then
					taskLabel.Text = "Writing code…"
				end
				if time_elapsed > 25 then
					taskLabel.Text = "Still working — hang tight…"
				end
			end
		end)
		if not okThink then
			pd.model_thinking_frame = nil
		end
	end
	
	local current_model_object = model_data
	if not current_model_object then
		pd.current_model = "auto"
		current_model_object = AISendHandler.get_model_data(pd.current_model)
	end
	if not current_model_object then
		ComposerControls.update(pd)
		DiffReviewUI.update(pd)
		return
	end
	if is_auto then
		-- Auto uses the free backend; no BYOK key needed
		pd.widget.App.BottomThread.ApiKeyInput.Visible = false
		pd.widget.App.BottomThread.ApiKeyHiddenLabel.Visible = false
		pd.widget.App.BottomThread.ShowApiKeyButton.Visible = false
		pd.widget.App.BottomThread.ApiKeyInput.PlaceholderText = "(Auto — no key needed)"
	else
		pd.widget.App.BottomThread.ShowApiKeyButton.Visible = true
		module.update_api_key_visibility(pd)
		if current_model_object.can_use_gg then
			pd.widget.App.BottomThread.ApiKeyInput.PlaceholderText = "(optional) API key"
		else
			pd.widget.App.BottomThread.ApiKeyInput.PlaceholderText = "API key (required)"
		end
	end

	if current_model_object.not_recommended then
		pd.widget.App.WarningFrame.WarningContent.Text = "We don't recommend using " .. current_model_object.name .. " for long scripts."
		pd.widget.App.WarningFrame.Visible = true
	else
		pd.widget.App.WarningFrame.Visible = false
	end

	ComposerControls.update(pd)
	DiffReviewUI.update(pd)

	-- Busy affordance on Send
	local send = pd.widget.App.BottomThread:FindFirstChild("SendButton")
	if send then
		send.Active = pd.model_bussy ~= true
		if send:IsA("ImageButton") or send:IsA("GuiButton") then
			send.AutoButtonColor = pd.model_bussy ~= true
		end
		pcall(function()
			send.ImageTransparency = if pd.model_bussy then 0.45 else 0
		end)
	end
end

return module


]]></ProtectedString>
				<string name="ScriptGuid">{3B271064-AA46-4DFA-8FB5-448472F8FFB0}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">WidgetWindow</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBX1d41d0cb80904a86aef70f160c82d3ae">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local module = {}
local FeedbackWidgetWindow = require(script.Parent.FeedbackWidgetWindow)

local cancel_menu_frame_hide_action = false
local cancel_model_frame_hide_action = false

function module.setup_model_select_frame(pd)
	pd.widget.App.BottomThread.CurrentModelButton.MouseButton1Click:Connect(function()
		cancel_model_frame_hide_action = true
		pd.widget.App.ModelSelectFrame.Visible = not pd.widget.App.ModelSelectFrame.Visible
	end)

	pd.widget.App.InputBegan:Connect(function(input, _processed)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			task.wait(0.1)
			if cancel_model_frame_hide_action then
				cancel_model_frame_hide_action = false
			else
				pd.widget.App.ModelSelectFrame.Visible = false
			end
		end
	end)
end

function module.setup_menu_frame(pd)
	pd.widget.App.BottomThread.OpenMenuButton.MouseButton1Click:Connect(function()
		cancel_menu_frame_hide_action = true
		pd.widget.App.MenuFrame.Visible = not pd.widget.App.MenuFrame.Visible
	end)

	pd.widget.App.InputBegan:Connect(function(input, _processed)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			task.wait(0.1)
			if cancel_menu_frame_hide_action then
				cancel_menu_frame_hide_action = false
			else
				pd.widget.App.MenuFrame.Visible = false
			end
		end
	end)

	pd.widget.App.MenuFrame.ClearButton.MouseButton1Click:Connect(function()
		local AppState = require(script.Parent.App.State)
		local AgentLoop = require(script.Parent.Agent.Loop)
		-- Invalidate the in-flight run, then stop it.
		pcall(function()
			AgentLoop.stop(pd)
		end)
		if typeof(pd.run_id) == "number" then
			pd.run_id += 1
		end
		pd._loop_owner = nil
		AppState.clearChat(pd)
		AppState.endRun(pd)
		if pd.model_thinking_frame then
			pcall(function()
				pd.model_thinking_frame:Destroy()
			end)
			pd.model_thinking_frame = nil
		end
		for _, v in ipairs(pd.widget.App.ChatHistory:GetChildren()) do
			if v.Name ~= "UIListLayout" then
				v:Destroy()
			end
		end
		local DiffReviewUI = require(script.Parent.App.DiffReviewUI)
		DiffReviewUI.update(pd)
		local ComposerControls = require(script.Parent.App.ComposerControls)
		ComposerControls.update(pd)
		if pd.spawn_system_bubble then
			pd.spawn_system_bubble("Chat cleared.")
		end
	end)

	pd.widget.App.MenuFrame.FeedbackButton.MouseButton1Click:Connect(function()
		FeedbackWidgetWindow.build_feedback_window(pd)
	end)

	pd.widget.App.MenuFrame.JoinSupportServerButton.MouseButton1Click:Connect(function()
		if cancel_menu_frame_hide_action then
			return
		end
		cancel_menu_frame_hide_action = true

		local old_text = pd.widget.App.MenuFrame.JoinSupportServerButton.TextLabel.Text
		pd.widget.App.MenuFrame.JoinSupportServerButton.TextLabel.Text = "Check output console!"
		print("Use the following link to join Vibe Coder plugin community (keewinek studios):")
		print("https://discord.gg/VCsGp8xCtf")
		task.wait(1)
		pd.widget.App.MenuFrame.JoinSupportServerButton.TextLabel.Text = old_text
		cancel_menu_frame_hide_action = false
	end)
end

return module

]]></ProtectedString>
				<string name="ScriptGuid">{2B2A504F-4FB9-4325-9CF1-41F8B5593494}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">WidgetModelSelectFrameOpener</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBX3a9326ba44954849ae7e2034e8dbc2b1">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local HttpService = game:GetService("HttpService")

local base64 = require(script.Parent.Libs.Base64)
local XOR = require(script.Parent.Libs.XOR)
local SHA256 = require(script.Parent.Libs.SHA256)

local SECRET = "Stealing these API keys is pointless because they use the free Gemini plan, just go to https://aistudio.google.com/apikey to create your own key."

local function stringToBuffer(str)
	local buf = buffer.create(#str)
	for i = 1, #str do
		buffer.writeu8(buf, i - 1, string.byte(str, i))
	end
	return buf
end

local function bufferToString(buf)
	local chars = {}
	for i = 0, buffer.len(buf) - 1 do
		chars[#chars + 1] = string.char(buffer.readu8(buf, i))
	end
	return table.concat(chars)
end

local function hex_to_buffer(hex)
	local len = #hex
	local buf = buffer.create(len / 2)
	for i = 1, len, 2 do
		local byte = tonumber(hex:sub(i, i+1), 16)
		buffer.writeu8(buf, (i-1)/2, byte)
	end
	return buf
end

local function splitByDot(str)
	local result = {}
	for part in string.gmatch(str, "([^%.]+)") do
		table.insert(result, part)
	end
	return result
end

local function gg_to_key(gg)
	local base64Buffer = stringToBuffer(gg)
	local rawBuffer = base64.decode(base64Buffer)

	local keyHashHex = SHA256.sha256(SECRET)
	local keyBuf = hex_to_buffer(keyHashHex)
	local key = XOR.keyFromPassword(keyBuf, buffer.len(rawBuffer))

	local decryptedBuffer = XOR.xorBuffers(rawBuffer, key)
	local full_string = bufferToString(decryptedBuffer)
	
	local parts = splitByDot(full_string)
	return parts[1]
end

local function fetch_gg()
	local url = "https://rbx-vibecoder-backend.keewinek.deno.net/api/gg"
	local success, response = pcall(function()
		return HttpService:GetAsync(url)
	end)

	if not success then
		warn("Failed to get gg from API:", response)
		return nil
	end

	local decoded
	success, decoded = pcall(function()
		return HttpService:JSONDecode(response)
	end)
	if not success then
		warn("Failed to decode JSON:", decoded)
		return nil
	end

	return decoded.gg
end

local function get_gg()
	local gg = fetch_gg()
	if not gg or gg == "" then
		-- Local fallback while Deploy secrets are empty
		local okLocal, response = pcall(function()
			return HttpService:GetAsync("http://127.0.0.1:8000/api/gg")
		end)
		if okLocal then
			local okJson, decoded = pcall(function()
				return HttpService:JSONDecode(response)
			end)
			if okJson and decoded and decoded.gg then
				gg = decoded.gg
			end
		end
	end
	if not gg or gg == "" then
		return nil
	end
	local ok, key = pcall(function()
		return gg_to_key(gg)
	end)
	if not ok or not key or key == "" then
		warn("Failed to decrypt gg:", key)
		return nil
	end
	return key
end

return {
	get_gg = get_gg,
}


]]></ProtectedString>
				<string name="ScriptGuid">{B3E5806A-799D-4A7A-82B3-0D86B1FB15C6}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">GgHandler</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBX109c4ef96b6f4c528208743adddc66f4">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local HttpService = game:GetService("HttpService")

local function gemini_build_body(messages_history, system_prompt)
	local contents = {}

	for _, message in ipairs(messages_history) do
		local role = message.role == "user" and "user" or "model"
		table.insert(contents, {
			role = role,
			parts = {
				{ text = message.content }
			}
		})
	end

	return HttpService:JSONEncode({
		systemInstruction = {
			parts = {
				{ text = system_prompt }
			}
		},
		contents = contents
	})
end

local function gemini_parse_response(data)
	local parts = data
		and data.candidates
		and data.candidates[1]
		and data.candidates[1].content
		and data.candidates[1].content.parts

	if not parts then
		return nil
	end

	local texts = {}
	for _, part in ipairs(parts) do
		if type(part.text) == "string" then
			table.insert(texts, part.text)
		end
	end

	if #texts == 0 then
		return nil
	end

	return table.concat(texts, "")
end

local function openai_build_body(messages_history, system_prompt, model)
	local messages = {}

	if system_prompt and system_prompt ~= "" then
		table.insert(messages, {
			role = "system",
			content = system_prompt
		})
	end

	for _, message in ipairs(messages_history) do
		table.insert(messages, {
			role = message.role == "user" and "user" or "assistant",
			content = message.content
		})
	end

	return HttpService:JSONEncode({
		model = model,
		messages = messages,
		stream = false
	})
end

local function build_claude_messages_body(messages_history, system_prompt, model_name)
	local messages = {}

	for _, message in ipairs(messages_history) do
		table.insert(messages, {
			role = message.role == "user" and "user" or "assistant",
			content = message.content
		})
	end

	local body = {
		model = model_name,
		messages = messages,
		max_tokens = 64000,
	}

	if system_prompt and system_prompt ~= "" then
		body.system = system_prompt
	end

	return HttpService:JSONEncode(body)
end

local gemini_endpoint = "https://generativelanguage.googleapis.com/v1beta/models/%model%:generateContent?key=%key%"
local gemini_headers = function(_api_key)
	return { ["Content-Type"] = "application/json" }
end

local openai_headers = function(api_key)
	return {
		["Content-Type"] = "application/json",
		["Authorization"] = "Bearer " .. api_key,
	}
end

local openai_parse = function(data)
	return data.choices[1].message.content
end

local claude_headers = function(api_key)
	return {
		["Content-Type"] = "application/json",
		["x-api-key"] = api_key,
		["anthropic-version"] = "2023-06-01",
	}
end

local claude_parse = function(data)
	return data.content and data.content[1] and data.content[1].text or ""
end

local model_registry = {
	-- Auto (our backend multi-provider gateway)
	{
		name = "auto",
		display_name = "Auto",
		is_auto = true,
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://rbx-vibecoder-backend.keewinek.deno.net/v1/chat/completions",
		build_body = function() return "{}" end,
		build_headers = function() return { ["Content-Type"] = "application/json" } end,
		parse_response = function() return nil end,
	},

	-- Google Gemini
	{
		name = "gemini-3.6-flash",
		can_use_gg = true,
		not_recommended = false,
		endpoint = gemini_endpoint,
		build_body = gemini_build_body,
		build_headers = gemini_headers,
		parse_response = gemini_parse_response,
	},
	{
		name = "gemini-3.5-flash",
		can_use_gg = true,
		not_recommended = false,
		endpoint = gemini_endpoint,
		build_body = gemini_build_body,
		build_headers = gemini_headers,
		parse_response = gemini_parse_response,
	},
	{
		name = "gemini-3.1-pro-preview",
		can_use_gg = false,
		not_recommended = false,
		endpoint = gemini_endpoint,
		build_body = gemini_build_body,
		build_headers = gemini_headers,
		parse_response = gemini_parse_response,
	},

	-- OpenAI
	{
		name = "gpt-5.6",
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://api.openai.com/v1/chat/completions",
		build_body = function(messages, prompt)
			return openai_build_body(messages, prompt, "gpt-5.6")
		end,
		build_headers = openai_headers,
		parse_response = openai_parse,
	},
	{
		name = "gpt-5.6-terra",
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://api.openai.com/v1/chat/completions",
		build_body = function(messages, prompt)
			return openai_build_body(messages, prompt, "gpt-5.6-terra")
		end,
		build_headers = openai_headers,
		parse_response = openai_parse,
	},
	{
		name = "gpt-5.6-luna",
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://api.openai.com/v1/chat/completions",
		build_body = function(messages, prompt)
			return openai_build_body(messages, prompt, "gpt-5.6-luna")
		end,
		build_headers = openai_headers,
		parse_response = openai_parse,
	},

	-- Anthropic Claude
	{
		name = "claude-sonnet-5",
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://api.anthropic.com/v1/messages",
		build_body = function(messages, system_prompt)
			return build_claude_messages_body(messages, system_prompt, "claude-sonnet-5")
		end,
		build_headers = claude_headers,
		parse_response = claude_parse,
	},
	{
		name = "claude-opus-4-8",
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://api.anthropic.com/v1/messages",
		build_body = function(messages, system_prompt)
			return build_claude_messages_body(messages, system_prompt, "claude-opus-4-8")
		end,
		build_headers = claude_headers,
		parse_response = claude_parse,
	},
	{
		name = "claude-haiku-4-5",
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://api.anthropic.com/v1/messages",
		build_body = function(messages, system_prompt)
			return build_claude_messages_body(messages, system_prompt, "claude-haiku-4-5-20251001")
		end,
		build_headers = claude_headers,
		parse_response = claude_parse,
	},
	{
		name = "claude-fable-5",
		can_use_gg = false,
		not_recommended = false,
		endpoint = "https://api.anthropic.com/v1/messages",
		build_body = function(messages, system_prompt)
			return build_claude_messages_body(messages, system_prompt, "claude-fable-5")
		end,
		build_headers = claude_headers,
		parse_response = claude_parse,
	},
}

return model_registry
]]></ProtectedString>
				<string name="ScriptGuid">{CE577970-C424-4A58-B52A-D460D6FFD4A9}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">ModelRegistry</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBX228a9b12de28423b968b0a07fd938a28">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local module = {}

local ModelRegistry = require(script.Parent.ModelRegistry)
local SystemInstructions = require(script.Parent.SystemInstructions)
local GgHandler = require(script.Parent.GgHandler)
local GamepassHandler = require(script.Parent.GamepassHandler)
local CheckUpdate = require(script.Parent.CheckUpdate)
local AgentLoop = require(script.Parent.Agent.Loop)
local DiffReviewUI = require(script.Parent.App.DiffReviewUI)
local ChatUI = require(script.Parent.App.ChatUI)
local AtMentions = require(script.Parent.App.AtMentions)
local Types = require(script.Parent.Agent.Types)
local PathUtil = require(script.Parent.Tools.PathUtil)
local State = require(script.Parent.App.State)

local TextService = game:GetService("TextService")
local HttpService = game:GetService("HttpService")

local FREE_MESSAGES_LIMIT = 5

function module.get_model_data(model_name)
	for _, v in ipairs(ModelRegistry) do
		if v.name == model_name then
			return v
		end
	end
	return nil
end

local function ensure_pd_tables(pd)
	if typeof(pd.history) ~= "table" then pd.history = {} end
	if typeof(pd.agent_messages) ~= "table" then pd.agent_messages = {} end
	if typeof(pd.pending_edits) ~= "table" then pd.pending_edits = {} end
	if typeof(pd.at_mentions) ~= "table" then pd.at_mentions = {} end
end

local function refresh_composer(pd)
	pcall(function()
		local ComposerControls = require(script.Parent.App.ComposerControls)
		ComposerControls.update(pd)
	end)
end

local function cleanup_thinking(pd)
	pd.model_bussy = false
	if pd.model_thinking_frame then
		pcall(function()
			pd.model_thinking_frame:Destroy()
		end)
		pd.model_thinking_frame = nil
	end
	refresh_composer(pd)
end

local function set_frame_textlabel_height(frame, textlabel)
	if not frame or not textlabel then
		return
	end
	textlabel.TextWrapped = true
	textlabel.Size = UDim2.new(0.95, 0, 0, 0)
	task.wait()
	local width = math.max(1, textlabel.AbsoluteSize.X)
	local textSize = TextService:GetTextSize(
		tostring(textlabel.Text or ""),
		textlabel.TextSize,
		textlabel.Font,
		Vector2.new(width, math.huge)
	)
	textlabel.Size = UDim2.new(0.95, 0, 0, textSize.Y)
	frame.Size = UDim2.new(frame.Size.X.Scale, frame.Size.X.Offset, 0, textSize.Y + 16)
end

local function scroll_chat_to_the_bottom(pd)
	if not pd.widget or not pd.widget:FindFirstChild("App") then
		return
	end
	local scrollingFrame = pd.widget.App:FindFirstChild("ChatHistory")
	if not scrollingFrame then
		return
	end
	task.wait()
	local layout = scrollingFrame:FindFirstChildOfClass("UIListLayout")
	local totalHeight
	if layout then
		totalHeight = layout.AbsoluteContentSize.Y + 20
	else
		totalHeight = 20
		for _, child in ipairs(scrollingFrame:GetChildren()) do
			if child:IsA("GuiObject") and child.Visible then
				totalHeight += child.AbsoluteSize.Y
			end
		end
	end
	scrollingFrame.CanvasSize = UDim2.new(0, 0, 0, totalHeight)
	task.wait()
	scrollingFrame.CanvasPosition = Vector2.new(0, math.max(0, totalHeight))
end

local function spawn_user_bubble(pd, text)
	if not pd.widget or not script.Parent.Prefabs:FindFirstChild("UserBubble") then
		return
	end
	local bubble = script.Parent.Prefabs.UserBubble:Clone()
	bubble.ContentLabel.Text = tostring(text or "")
	bubble.Parent = pd.widget.App.ChatHistory
	set_frame_textlabel_height(bubble, bubble.ContentLabel)
	scroll_chat_to_the_bottom(pd)
end

local function spawn_system_bubble(pd, text)
	if not pd.widget or not script.Parent.Prefabs:FindFirstChild("SystemBubble") then
		return
	end
	local bubble = script.Parent.Prefabs.SystemBubble:Clone()
	bubble.ContentLabel.Text = tostring(text or "")
	bubble.Parent = pd.widget.App.ChatHistory
	set_frame_textlabel_height(bubble, bubble.ContentLabel)
	scroll_chat_to_the_bottom(pd)
end

local function spawn_model_bubble(pd, text)
	if not pd.widget or not script.Parent.Prefabs:FindFirstChild("ModelBubble") then
		return
	end
	local bubble = script.Parent.Prefabs.ModelBubble:Clone()
	bubble.ContentLabel.Text = tostring(text or "")
	bubble.Parent = pd.widget.App.ChatHistory
	set_frame_textlabel_height(bubble, bubble.ContentLabel)
	scroll_chat_to_the_bottom(pd)
end

local function spawn_model_thinking_frame(pd)
	if not pd.widget or not script.Parent.Prefabs:FindFirstChild("ModelThinkingFrame") then
		return nil
	end
	local frame = script.Parent.Prefabs.ModelThinkingFrame:Clone()
	frame.Parent = pd.widget.App.ChatHistory
	scroll_chat_to_the_bottom(pd)
	return frame
end

function module.attach_session_helpers(pd)
	pd.spawn_system_bubble = function(text)
		spawn_system_bubble(pd, text)
	end
end

local function bump_usage(pd)
	local key = "vibe-coder-usage-" .. os.date("%Y-%m-%d")
	local todays = pd.plugin:GetSetting(key) or 0
	pd.plugin:SetSetting(key, todays + 1)
end

local function parse_response_string(response_string)
	if type(response_string) ~= "string" then
		return { analysis = "", message = "", code = "" }
	end
	local analysis = response_string:match("=== ANALYSIS ===\n(.-)\n=== MESSAGE ===")
	local message, code
	if response_string:find("=== CODE ===", 1, true) then
		message = response_string:match("=== MESSAGE ===\n(.-)\n=== CODE ===")
		code = response_string:match("=== CODE ===\n(.*)")
	else
		message = response_string:match("=== MESSAGE ===\n(.*)")
		code = ""
	end
	if not code then
		code = ""
	end
	local out = {
		analysis = analysis and analysis:match("^%s*(.-)%s*$") or "",
		message = message and message:match("^%s*(.-)%s*$") or "",
		code = code,
	}
	if out.message == "" then
		out.message = response_string
	end
	return out
end

local function handle_ai_interaction(pd, user_prompt, system_prompt, user_api_key)
	local model_data = module.get_model_data(pd.current_model)
	if not model_data then
		spawn_model_bubble(pd, "Model not found: " .. tostring(pd.current_model))
		return false
	end

	local api_key = user_api_key or ""
	local used_gg = false
	if api_key == "" and model_data.can_use_gg then
		local okGg, ggKey = pcall(function()
			return GgHandler.get_gg()
		end)
		if okGg and typeof(ggKey) == "string" and ggKey ~= "" then
			api_key = ggKey
			used_gg = true
		end
	end

	if api_key == "" then
		spawn_model_bubble(pd, "Please provide an API key first.")
		return false
	end

	pd.model_thinking_frame = spawn_model_thinking_frame(pd)
	pd.model_thinking_started = tick()

	local selected_script_object = pd.selected_script
	pd.history[#pd.history + 1] = { role = "user", content = user_prompt }

	local endpoint = model_data.endpoint
	endpoint = endpoint:gsub("%%model%%", pd.current_model)
	endpoint = endpoint:gsub("%%key%%", api_key)

	local headers = model_data.build_headers(api_key)
	local body = model_data.build_body(pd.history, system_prompt)

	local success, response = pcall(function()
		return HttpService:RequestAsync({
			Url = endpoint,
			Method = "POST",
			Headers = headers,
			Body = body,
		})
	end)

	if (not success) or (typeof(response) ~= "table") or (not response.Success) then
		if used_gg then
			spawn_model_bubble(pd, "Free shared key is busy. Paste your own API key, or use Auto.")
		else
			spawn_model_bubble(pd, "Could not reach " .. model_data.name .. ". Check your API key / network.")
		end
		return false
	end

	local data
	local okDecode = pcall(function()
		data = HttpService:JSONDecode(response.Body)
	end)
	if not okDecode then
		spawn_model_bubble(pd, "Failed to parse model response.")
		return false
	end

	local reply_string = model_data.parse_response(data)
	if not reply_string then
		spawn_model_bubble(pd, "Model returned no usable text.")
		return false
	end

	local reply_object = parse_response_string(reply_string)
	if not reply_object or reply_object.message == "" then
		spawn_model_bubble(pd, "Model response could not be parsed. Try another model or Auto.")
		return false
	end

	pd.history[#pd.history + 1] = { role = "model", content = reply_string }
	spawn_model_bubble(pd, reply_object.message)
	bump_usage(pd)

	if not selected_script_object or not selected_script_object.Parent then
		return true
	end

	local oldSource = ""
	pcall(function()
		oldSource = selected_script_object.Source
	end)
	if reply_object.code == "" or string.gsub(reply_object.code, "%s", "") == string.gsub(oldSource, "%s", "") then
		return true
	end

	local edit = Types.makePendingEdit({
		id = Types.newId("byok"),
		path = PathUtil.getFullName(selected_script_object),
		instance = selected_script_object,
		oldSource = oldSource,
		newSource = reply_object.code,
		action = "edit",
		applied = false,
	})
	State.addPendingEdit(pd, edit)
	ChatUI.spawnEditCard(pd, edit)
	DiffReviewUI.update(pd)
	spawn_system_bubble(pd, "Queued edit for review — Accept to apply.")
	return true
end

function module.on_send_button_click(pd)
	if typeof(pd) ~= "table" or not pd.widget then
		return
	end
	ensure_pd_tables(pd)
	module.attach_session_helpers(pd)

	if pd.model_bussy then
		spawn_system_bubble(pd, "Still working… press Stop, or wait.")
		return
	end

	local user_prompt = tostring(pd.widget.App.BottomThread.ChatInputTextBox.Text or "")
	user_prompt = user_prompt:match("^%s*(.-)%s*$") or ""
	local user_api_key = tostring(pd.widget.App.BottomThread.ApiKeyInput.Text or "")
	if user_prompt == "" then
		return
	end

	local todays_interactions = pd.plugin:GetSetting("vibe-coder-usage-" .. os.date("%Y-%m-%d")) or 0
	if not GamepassHandler.get_gamepass_ownership() and todays_interactions >= FREE_MESSAGES_LIMIT then
		pd.widget.BuyProFrame.Visible = true
		pd.widget.BuyProFrame.Header.Text = "You have reached your FREE daily messages limit."
		return
	end

	-- Mark busy BEFORE any yielding UI work to prevent double-send races.
	pd.model_bussy = true
	refresh_composer(pd)

	local model_data_early = module.get_model_data(pd.current_model)
	local is_auto_early = model_data_early and model_data_early.is_auto
	-- Optional focus change (Cursor-style). Don't wipe Auto memory on deselect.
	if pd.last_message_selected_script ~= pd.selected_script then
		if pd.selected_script ~= nil and pd.last_message_selected_script ~= nil then
			spawn_system_bubble(pd, "--- focused script changed ---")
			if not is_auto_early then
				pd.history = {}
			end
		elseif pd.selected_script ~= nil and pd.last_message_selected_script == nil then
			spawn_system_bubble(pd, "Focused: " .. tostring(pd.selected_script.Name))
		end
	end
	pd.last_message_selected_script = pd.selected_script
	pd.widget.App.BottomThread.ChatInputTextBox.Text = ""

	-- Persist API key on send (not every UI tick)
	pcall(function()
		pd.plugin:SetSetting(
			"vibe-coder-secret-" .. (pd.current_model:gsub("[^%w]", "")),
			user_api_key
		)
	end)

	pcall(function()
		local version = CheckUpdate.is_update_required()
		if version ~= "no" then
			spawn_system_bubble(pd, version .. " is out! Please go to https://rbxvibecoder.com and update your Vibe Coder.")
		end
	end)

	spawn_user_bubble(pd, user_prompt)
	pcall(function()
		AtMentions.capture(pd, user_prompt)
	end)
	local mentionSummary = ""
	pcall(function()
		mentionSummary = AtMentions.summary(pd) or ""
	end)
	if mentionSummary ~= "" then
		spawn_system_bubble(pd, mentionSummary)
	end

	local model_data = module.get_model_data(pd.current_model)
	if model_data and model_data.is_auto then
		pd.model_thinking_frame = spawn_model_thinking_frame(pd)
		pd.model_thinking_started = tick()
		pd.on_agent_step = function(kind, text, extra)
			pcall(function()
				if kind == "tool" then
					local detail = ""
					if typeof(extra) == "table" then
						detail = tostring(extra.detail or extra.path or "")
					end
					ChatUI.spawnTool(pd, text, detail)
				elseif kind == "diff" then
					local path = text
					if typeof(extra) == "table" and extra.path then
						path = extra.path
					end
					path = tostring(path):gsub("^Queued change:%s*", "")
					DiffReviewUI.notifyQueued(pd, path)
				end
			end)
		end

		local okRun, pack = pcall(function()
			local text, err = AgentLoop.run(pd, user_prompt)
			return { text = text, err = err }
		end)
		if not okRun then
			spawn_model_bubble(pd, "Agent crashed: " .. tostring(pack))
		else
			local pending = 0
			for _, e in ipairs(pd.pending_edits or {}) do
				if not e.applied then
					pending += 1
				end
			end
			if pack.err then
				local errText = tostring(pack.err)
				if errText == "Stopped" then
					errText = "Stopped."
				end
				spawn_model_bubble(pd, errText)
			elseif pack.text and pack.text ~= "" then
				spawn_model_bubble(pd, pack.text)
				bump_usage(pd)
			elseif pending > 0 then
				-- Tool-only turn that queued edits still counts as a successful run.
				bump_usage(pd)
			end
			if not pack.err and pending > 0 then
				pcall(function()
					ChatUI.spawnCardsForPending(pd)
				end)
				spawn_system_bubble(pd, string.format("%d pending edit(s) — Accept/Reject per file, or use Diff Review.", pending))
			end
		end
		cleanup_thinking(pd)
		return
	end

	local system_prompt = SystemInstructions.get_system_instructions(pd)
	local okByok, byokErr = pcall(function()
		return handle_ai_interaction(pd, user_prompt, system_prompt, user_api_key)
	end)
	if not okByok then
		spawn_model_bubble(pd, "Request failed: " .. tostring(byokErr))
	end
	cleanup_thinking(pd)
end

return module

]]></ProtectedString>
				<string name="ScriptGuid">{161C3D43-D28B-4B6D-93E0-249568D69AAA}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">AISendHandler</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBX21b2dff98a7e4e13926dd4e2528d5963">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local module = {}

local MAX_OBJECTS_TO_PRINT = 100
local MAX_DEPTH_FOR_CONTEXT = 16

local function getPathUpTo(target_object)
	local segments = {}
	local current = target_object
	while current and current ~= game do
		table.insert(segments, 1, current.Name)
		current = current.Parent
	end
	return table.concat(segments, " > ")
end

local function build_hierarchy_string_recursive(
	current_obj,
	indent_level,
	feature_object_to_mark,
	current_lines,
	printed_objects_count_ref,
	max_depth
)
	if printed_objects_count_ref.count >= MAX_OBJECTS_TO_PRINT then
		return
	end
	if not current_obj or current_obj == game or indent_level > max_depth then
		return
	end

	local indent = string.rep("  ", indent_level)
	local marker = current_obj == feature_object_to_mark and " (selected)" or ""
	local entry = indent .. "- " .. current_obj.Name .. " (" .. current_obj.ClassName .. ")" .. marker
	table.insert(current_lines, entry)
	printed_objects_count_ref.count = printed_objects_count_ref.count + 1

	local children = current_obj:GetChildren()
	table.sort(children, function(a, b)
		return a.Name < b.Name
	end)

	for _, child in ipairs(children) do
		if printed_objects_count_ref.count >= MAX_OBJECTS_TO_PRINT then
			break
		end
		build_hierarchy_string_recursive(
			child,
			indent_level + 1,
			feature_object_to_mark,
			current_lines,
			printed_objects_count_ref,
			max_depth
		)
	end
end

function module.get_game_hierarchy_string(feature_object)
	if not feature_object or not feature_object.Parent then
		return "Unknown location"
	end

	local context = {}
	local printed_objects_count = { count = 0 }

	local selected_object_path = getPathUpTo(feature_object)
	table.insert(context, "Selected object path: " .. selected_object_path)
	table.insert(context, "")

	local hierarchy_snapshot_root = feature_object
	while hierarchy_snapshot_root.Parent and hierarchy_snapshot_root.Parent ~= game do
		hierarchy_snapshot_root = hierarchy_snapshot_root.Parent
	end

	table.insert(
		context,
		"Game Hierarchy Snapshot (max "
			.. MAX_OBJECTS_TO_PRINT
			.. " objects, max depth "
			.. MAX_DEPTH_FOR_CONTEXT
			.. "):"
	)
	table.insert(context, "----------------------------------------------------")

	build_hierarchy_string_recursive(
		hierarchy_snapshot_root,
		0,
		feature_object,
		context,
		printed_objects_count,
		MAX_DEPTH_FOR_CONTEXT
	)

	if printed_objects_count.count >= MAX_OBJECTS_TO_PRINT then
		table.insert(context, "\n... (Hierarchy truncated due to object limit)")
	end

	local marked = false
	for _, line in ipairs(context) do
		if string.find(line, "(selected)", 1, true) then
			marked = true
			break
		end
	end
	if not marked then
		table.insert(
			context,
			"\nHierarchy note: selected object may be deeper than snapshot depth — see path above."
		)
	end

	return table.concat(context, "\n")
end

return module
]]></ProtectedString>
				<string name="ScriptGuid">{423CDCBD-4250-4532-9331-3A3B9B169D6C}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">PrintGameHierarhy</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="Script" referent="RBX7ca8963b508e442893f82801f737fec4">
			<Properties>
				<ProtectedString name="Source"><![CDATA[local WidgetWindow = require(script.Parent.WidgetWindow)
local GamepassHandler = require(script.Parent.GamepassHandler)
local ModelRegistry = require(script.Parent.ModelRegistry)
local AppState = require(script.Parent.App.State)

local DEFAULT_MODEL = AppState.DEFAULT_MODEL -- "auto"

if not plugin:GetSetting("vibe-coder-migrated-auto-v1") then
	plugin:SetSetting("vibe-coder-last-model", DEFAULT_MODEL)
	plugin:SetSetting("vibe-coder-migrated-auto-v1", true)
end

local function resolve_current_model()
	local saved = plugin:GetSetting("vibe-coder-last-model") or DEFAULT_MODEL
	for _, model in ipairs(ModelRegistry) do
		if model.name == saved then
			return saved
		end
	end
	return DEFAULT_MODEL
end

local pd = {
	selected_script = nil,
	last_message_selected_script = nil,
	widget = nil,
	api_key_hidden = plugin:GetSetting("vibe-coder-api-key-hidden") or false,
	model_thinking_frame = nil,
	model_thinking_started = 0,
	model_bussy = false,
	plugin = plugin,
	current_model = resolve_current_model(),
	gamepass_ownership = GamepassHandler.get_gamepass_ownership(),
	history = {},
	agent_messages = {},
	pending_edits = {},
	run_id = 0,
	abort_requested = false,
	at_mentions = {},
}

local toolbar = plugin:CreateToolbar("Vibe Coder")
local plugin_button
if pd.gamepass_ownership then
	plugin_button = toolbar:CreateButton("Vibe Coder PRO", "Vibe Coder v1.0 by keewinek.", "rbxassetid://115853486982676")
else
	plugin_button = toolbar:CreateButton("Vibe Coder", "Vibe Coder v1.0 by keewinek.", "rbxassetid://129168231652243")
end
plugin_button.ClickableWhenViewportHidden = true

WidgetWindow.build_widget(pd)

plugin_button.Click:Connect(function()
	if pd.widget then
		pd.widget.Enabled = not pd.widget.Enabled
	end
end)

local lastSel, lastBusy, lastModel, lastThinking = nil, nil, nil, nil

local function plugin_tick()
	if not pd.widget or not pd.widget.Enabled then
		return
	end

	local Selection = game:GetService("Selection")
	local selected = Selection:Get()[1]
	if selected and selected:IsA("LuaSourceContainer") then
		pd.selected_script = selected
	else
		pd.selected_script = nil
	end

	local thinking = pd.model_thinking_frame
	local dirty = pd.selected_script ~= lastSel
		or pd.model_bussy ~= lastBusy
		or pd.current_model ~= lastModel
		or thinking ~= lastThinking
		or thinking ~= nil -- animate thinking timer while visible

	if dirty then
		lastSel = pd.selected_script
		lastBusy = pd.model_bussy
		lastModel = pd.current_model
		lastThinking = thinking
		WidgetWindow.update_ui(pd)
	end
end

GamepassHandler.start_pro_ownership_task(pd)

task.defer(function()
	while true do
		task.wait()
		local success, message = pcall(plugin_tick)
		if not success then
			warn("[Vibe Coder] UI tick error:", message, "— please report to keewinek@gmail.com")
			task.wait(2)
		end
	end
end)
]]></ProtectedString>
				<bool name="Disabled">false</bool>
				<Content name="LinkedSource"><null></null></Content>
				<token name="RunContext">0</token>
				<string name="ScriptGuid">{4E27C2EA-0816-468F-8E92-B68F91982143}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">Plugin</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBXdedf8219c9574a16941d337478d884ab">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local PrintGameHierarhy = require(script.Parent.PrintGameHierarhy)
local module = {}

local SYSTEM_PROMPT = [[
You are Vibe Coder, an expert Roblox Studio AI scripting agent. You run inside a Roblox Studio plugin and you edit and write full Luau scripts for the user.

You MUST use the following plain text formatting in your response, as it will be automatically parsed by the plugin:

=== ANALYSIS ===
(Describe your thinking process, consider different solutions, possible obstacles)

=== MESSAGE ===
(Message that will be displayed to the user in the chat in the plugin's window. Please don't use markdown formatting, codeblocks and stuff like that, the plugin will display just plain text)

=== CODE ===
(COMPLETE, FULLY rewritten and working %script_name% %script_type% (content of the script will be given in this system prompt later), with ALL functions, variables, and logic in plain text - no code blocks)

The plugin has NO ABILITY to merge, patch, or combine code. It can ONLY replace the entire script with exactly what you provide in the CODE section.

MANDATORY:
- Copy the ENTIRE original script into the CODE section and apply changes there
- Never write partial snippets or "rest of script remains the same"
- CODE must be a complete standalone script

When writing this prompt, user has focused the following %script_type% named '%script_name%' (content of the script):
%script_content%
--- END OF SCRIPT ---
The script is located in this game hierarchy:
%hierarchy%

FINAL REMINDER: Provide the COMPLETE script in CODE. No shortcuts.
]]

local CHAT_ONLY_PROMPT = [[
You are Vibe Coder, an expert Roblox Studio AI scripting assistant inside a Studio plugin chat.

The user has not focused a specific script. Reply helpfully in this plain format:

=== ANALYSIS ===
(Brief thinking)

=== MESSAGE ===
(Your reply to the user — plain text only, no markdown code fences)

Do NOT include a === CODE === section unless the user clearly pastes a full script to rewrite.
If they want multi-file edits in the place, tell them to switch the model to Auto (free agent with tools).
If they focus/select a script in Studio, you can rewrite that whole file on the next message.
Keep answers concise and practical for Roblox Luau.
]]

local function get_script_type(source_script)
	if not source_script then
		return "Script"
	end
	if source_script:IsA("ModuleScript") then
		return "Module Script"
	end
	if source_script:IsA("Script") then
		return "Server Script"
	end
	if source_script:IsA("LocalScript") then
		return "Local Script"
	end
	return "Script"
end

local function plainReplace(str, target, replacement)
	if target == "" then
		return str
	end
	local parts = {}
	local i = 1
	local tlen = #target
	while true do
		local j = string.find(str, target, i, true)
		if not j then
			table.insert(parts, string.sub(str, i))
			break
		end
		table.insert(parts, string.sub(str, i, j - 1))
		table.insert(parts, replacement)
		i = j + tlen
	end
	return table.concat(parts)
end

function module.get_system_instructions(pd)
	local focused = pd.selected_script
	if not focused or not focused.Parent or not focused:IsA("LuaSourceContainer") then
		return CHAT_ONLY_PROMPT
	end

	local script_content = ""
	pcall(function()
		script_content = focused.Source
	end)
	local script_type = get_script_type(focused)
	local script_name = focused.Name
	local hierarchy = PrintGameHierarhy.get_game_hierarchy_string(focused)

	local out_prompt = SYSTEM_PROMPT
	out_prompt = plainReplace(out_prompt, "%script_type%", script_type)
	out_prompt = plainReplace(out_prompt, "%script_name%", script_name)
	out_prompt = plainReplace(out_prompt, "%hierarchy%", hierarchy)
	out_prompt = plainReplace(out_prompt, "%script_content%", script_content)
	return out_prompt
end

return module
]]></ProtectedString>
				<string name="ScriptGuid">{AF020E13-BBDB-4D31-8392-ED767FAFC236}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">SystemInstructions</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBXb496941295934f6a9a80411cb5260448">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local module = {}
local HttpService = game:GetService("HttpService")

local widget_info = DockWidgetPluginGuiInfo.new(
	Enum.InitialDockState.Float,
	true,
	false,
	600,
	400,
	380,
	300
)

local BACKEND_FEEDBACK_URL = "https://rbx-vibecoder-backend.keewinek.deno.net/api/feedback"
local LOCAL_FEEDBACK_URL = "http://127.0.0.1:8000/api/feedback"

local activeFeedbackWidget = nil

local function postFeedback(message)
	local body = HttpService:JSONEncode({ message = message })
	local urls = { BACKEND_FEEDBACK_URL, LOCAL_FEEDBACK_URL }
	local lastErr = nil
	for _, url in ipairs(urls) do
		local ok, response = pcall(function()
			return HttpService:RequestAsync({
				Url = url,
				Method = "POST",
				Headers = { ["Content-Type"] = "application/json" },
				Body = body,
			})
		end)
		if ok and typeof(response) == "table" and response.Success then
			return true, nil
		end
		if ok and typeof(response) == "table" then
			lastErr = tostring(response.StatusCode) .. " " .. tostring(response.Body)
		else
			lastErr = tostring(response)
		end
	end
	return false, lastErr
end

function module.build_feedback_window(pd)
	if activeFeedbackWidget and activeFeedbackWidget.Parent then
		activeFeedbackWidget.Enabled = true
		return activeFeedbackWidget
	end

	local widget = pd.plugin:CreateDockWidgetPluginGui("VibeCoderFeedbackWidget", widget_info)
	widget.Title = "Vibe Coder Feedback"
	widget.Enabled = true
	activeFeedbackWidget = widget

	for _, v in ipairs(script.Parent.Prefabs.FeedbackGUI:GetChildren()) do
		local clone = v:Clone()
		clone.Parent = widget
	end

	widget:BindToClose(function()
		pcall(function()
			widget:Destroy()
		end)
		if activeFeedbackWidget == widget then
			activeFeedbackWidget = nil
		end
	end)

	widget.App.SendButton.MouseButton1Click:Connect(function()
		if widget.App.SendButton.Text ~= "Send" then
			return
		end

		local message = widget.App.FeedbackInput.Text
		if #message < 5 then
			widget.App.SendButton.Text = "Message is too short!"
			task.wait(1)
			if widget and widget.Parent then
				widget.App.SendButton.Text = "Send"
			end
			return
		end

		widget.App.SendButton.Text = "Sending..."
		local success, err = postFeedback(message)
		if success then
			widget.App.SendButton.Text = "Sent!"
			task.wait(1)
			if widget and widget.Parent then
				widget.App.FeedbackInput.Text = ""
				widget.Enabled = false
				widget:Destroy()
			end
			if activeFeedbackWidget == widget then
				activeFeedbackWidget = nil
			end
			return
		else
			widget.App.SendButton.Text = "Error!"
			warn("Vibe Coder feedback failed:", err)
			task.wait(1)
		end

		if widget and widget.Parent then
			widget.App.SendButton.Text = "Send"
		end
	end)

	return widget
end

return module

]]></ProtectedString>
				<string name="ScriptGuid">{E3965072-934B-4334-AEC3-C74F72B82CEA}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">FeedbackWidgetWindow</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBXae8e6ddcf2b84b9a9c47cdeaced55d0c">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local module = {}

-- PRO unlock: catalog T-Shirt (legacy "gamepass" naming kept for settings/UI).
module.SHIRT_ID = 79884753121491
module.SHIRT_URL = "https://www.roblox.com/catalog/" .. module.SHIRT_ID

module.USER_ID = game:GetService("StudioService"):GetUserId()

function module.get_shirt_ownership()
	local ok, owns = pcall(function()
		local player = game:GetService("Players"):GetPlayerByUserId(module.USER_ID)
			or game:GetService("Players").LocalPlayer
		if not player then
			return false
		end
		return game:GetService("MarketplaceService"):PlayerOwnsAsset(player, module.SHIRT_ID)
	end)
	return ok and owns == true
end

function module.get_gamepass_ownership()
	return module.get_shirt_ownership()
end

function module.update_ui_for_free_tier(pd)
	if pd.widget and pd.widget.App and pd.widget.App:FindFirstChild("ModelSelectFrame") then
		local pro = pd.widget.App.ModelSelectFrame:FindFirstChild("ProLabel")
		if pro then
			pro.Visible = true
		end
	end
end

function module.update_ui_for_pro_tier(pd)
	if not pd.widget then
		return
	end
	if pd.widget.App and pd.widget.App:FindFirstChild("ModelSelectFrame") then
		local pro = pd.widget.App.ModelSelectFrame:FindFirstChild("ProLabel")
		if pro then
			pro.Visible = false
		end
	end
	if pd.widget:FindFirstChild("BuyProFrame") then
		pd.widget.BuyProFrame.Visible = false
	end
	local base = script.Parent.VersionTitle.Value or "Vibe Coder"
	pd.widget.Title = base .. " PRO"
end

function module.start_pro_ownership_task(pd)
	if module.get_shirt_ownership() then
		pd.gamepass_ownership = true
		module.update_ui_for_pro_tier(pd)
	else
		pd.gamepass_ownership = false
		module.update_ui_for_free_tier(pd)
	end

	task.spawn(function()
		while task.wait(2) do
			if module.get_shirt_ownership() then
				pd.gamepass_ownership = true
				module.update_ui_for_pro_tier(pd)
				break
			end
		end
	end)
end

return module
]]></ProtectedString>
				<string name="ScriptGuid">{CCF0E175-A015-4436-90E4-3EA083AC7C87}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">GamepassHandler</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="ModuleScript" referent="RBX78fb76705a9044daa231aefbd7850323">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<ProtectedString name="Source"><![CDATA[local module = {}

local HttpService = game:GetService("HttpService")

local VERSION_API_URL = "https://rbxvibecoder.com/api/get_version"
local BACKEND_VERSION_URL = "https://rbx-vibecoder-backend.keewinek.deno.net/api/plugin-version"
local LOCAL_VERSION_URL = "http://127.0.0.1:8000/api/plugin-version"

local function parseVersion(text)
	text = tostring(text or "")
	local a, b, c = text:match("[vV]?(%d+)%.(%d+)%.(%d+)")
	if a then
		return { tonumber(a), tonumber(b), tonumber(c) }
	end
	local x, y = text:match("[vV]?(%d+)%.(%d+)")
	if x then
		return { tonumber(x), tonumber(y), 0 }
	end
	return nil
end

local function isNewer(remote, localV)
	local r = parseVersion(remote)
	local l = parseVersion(localV)
	if not r or not l then
		return false
	end
	for i = 1, 3 do
		if r[i] > l[i] then
			return true
		end
		if r[i] < l[i] then
			return false
		end
	end
	return false
end

local function fetchVersion(url)
	local success, response = pcall(function()
		return HttpService:GetAsync(url)
	end)
	if not success then
		return nil
	end
	local okJson, decoded = pcall(function()
		return HttpService:JSONDecode(response)
	end)
	if okJson and typeof(decoded) == "table" then
		return decoded.display or decoded.version
	end
	return nil
end

function module.is_update_required()
	local localVersionString = script.Parent.VersionTitle.Value
	local remoteVersionString = fetchVersion(VERSION_API_URL)
		or fetchVersion(BACKEND_VERSION_URL)
		or fetchVersion(LOCAL_VERSION_URL)

	if not remoteVersionString then
		return "no"
	end
	if isNewer(remoteVersionString, localVersionString) then
		return tostring(remoteVersionString)
	end
	return "no"
end

return module

]]></ProtectedString>
				<string name="ScriptGuid">{E7D61F42-6DFD-4F2D-9E6E-E6C0630F983A}</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">CheckUpdate</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="Folder" referent="RBX10440a2638a14924b604628c3e2c71c6">
			<Properties>
				<Color3 name="IconTint">
					<R>0</R>
					<G>0</G>
					<B>0</B>
				</Color3>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">Prefabs</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
			<Item class="Frame" referent="RBX5b4da385bdf44cfa845d263165f6afe7">
				<Properties>
					<token name="Style">0</token>
					<bool name="Active">false</bool>
					<Vector2 name="AnchorPoint">
						<X>0.5</X>
						<Y>1</Y>
					</Vector2>
					<token name="AutomaticSize">0</token>
					<Color3 name="BackgroundColor3">
						<R>0.345098048</R>
						<G>0.427451015</G>
						<B>0.490196109</B>
					</Color3>
					<float name="BackgroundTransparency">0</float>
					<Color3 name="BorderColor3">
						<R>0</R>
						<G>0</G>
						<B>0</B>
					</Color3>
					<token name="BorderMode">0</token>
					<int name="BorderSizePixel">0</int>
					<bool name="ClipsDescendants">false</bool>
					<bool name="Draggable">false</bool>
					<bool name="Interactable">true</bool>
					<int name="LayoutOrder">0</int>
					<Ref name="NextSelectionDown">null</Ref>
					<Ref name="NextSelectionLeft">null</Ref>
					<Ref name="NextSelectionRight">null</Ref>
					<Ref name="NextSelectionUp">null</Ref>
					<UDim2 name="Position">
						<XS>0.5</XS>
						<XO>0</XO>
						<YS>0.0624782071</YS>
						<YO>0</YO>
					</UDim2>
					<float name="Rotation">0</float>
					<bool name="Selectable">false</bool>
					<Ref name="SelectionImageObject">null</Ref>
					<int name="SelectionOrder">0</int>
					<token name="Sink">0</token>
					<UDim2 name="Size">
						<XS>0.850000024</XS>
						<XO>0</XO>
						<YS>0.0624782741</YS>
						<YO>0</YO>
					</UDim2>
					<token name="SizeConstraint">0</token>
					<bool name="Visible">true</bool>
					<int name="ZIndex">1</int>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">UserBubble</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="UICorner" referent="RBX31bb29d86e394d81b55c90c43f49babb">
					<Properties>
						<UDim name="BottomLeftRadius">
							<S>0</S>
							<O>8</O>
						</UDim>
						<UDim name="BottomRightRadius">
							<S>0</S>
							<O>8</O>
						</UDim>
						<UDim name="TopLeftRadius">
							<S>0</S>
							<O>8</O>
						</UDim>
						<UDim name="TopRightRadius">
							<S>0</S>
							<O>8</O>
						</UDim>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">UICorner</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
				</Item>
				<Item class="TextLabel" referent="RBXfe8f7f7d027442b7a954de24de9e033a">
					<Properties>
						<Font name="FontFace">
							<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
							<Weight>400</Weight>
							<Style>Normal</Style>
						</Font>
						<float name="LineHeight">1</float>
						<string name="LocalizationMatchIdentifier"></string>
						<string name="LocalizationMatchedSourceText"></string>
						<int name="MaxVisibleGraphemes">-1</int>
						<string name="OpenTypeFeatures"></string>
						<bool name="RichText">false</bool>
						<string name="Text">User Content</string>
						<Color3 name="TextColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<token name="TextDirection">0</token>
						<bool name="TextScaled">false</bool>
						<float name="TextSize">14</float>
						<Color3 name="TextStrokeColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<float name="TextStrokeTransparency">1</float>
						<float name="TextTransparency">0</float>
						<token name="TextTruncate">0</token>
						<bool name="TextWrapped">true</bool>
						<token name="TextXAlignment">0</token>
						<token name="TextYAlignment">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0.5</X>
							<Y>0.5</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<float name="BackgroundTransparency">1</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0.5</XS>
							<XO>0</XO>
							<YS>0.5</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>0.899999976</XS>
							<XO>0</XO>
							<YS>0.75</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">1</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">ContentLabel</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
				</Item>
			</Item>
			<Item class="Frame" referent="RBX92ca7c72b6cb4c88a0893d7f7494da3d">
				<Properties>
					<token name="Style">0</token>
					<bool name="Active">false</bool>
					<Vector2 name="AnchorPoint">
						<X>0.5</X>
						<Y>1</Y>
					</Vector2>
					<token name="AutomaticSize">0</token>
					<Color3 name="BackgroundColor3">
						<R>0.345098048</R>
						<G>0.427451015</G>
						<B>0.490196109</B>
					</Color3>
					<float name="BackgroundTransparency">1</float>
					<Color3 name="BorderColor3">
						<R>0</R>
						<G>0</G>
						<B>0</B>
					</Color3>
					<token name="BorderMode">0</token>
					<int name="BorderSizePixel">0</int>
					<bool name="ClipsDescendants">false</bool>
					<bool name="Draggable">false</bool>
					<bool name="Interactable">true</bool>
					<int name="LayoutOrder">0</int>
					<Ref name="NextSelectionDown">null</Ref>
					<Ref name="NextSelectionLeft">null</Ref>
					<Ref name="NextSelectionRight">null</Ref>
					<Ref name="NextSelectionUp">null</Ref>
					<UDim2 name="Position">
						<XS>0.5</XS>
						<XO>0</XO>
						<YS>0.0624782071</YS>
						<YO>0</YO>
					</UDim2>
					<float name="Rotation">0</float>
					<bool name="Selectable">false</bool>
					<Ref name="SelectionImageObject">null</Ref>
					<int name="SelectionOrder">0</int>
					<token name="Sink">0</token>
					<UDim2 name="Size">
						<XS>0.850000024</XS>
						<XO>0</XO>
						<YS>0.25</YS>
						<YO>0</YO>
					</UDim2>
					<token name="SizeConstraint">0</token>
					<bool name="Visible">true</bool>
					<int name="ZIndex">1</int>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ModelBubble</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="TextLabel" referent="RBX4f865925fd694ab5b530370275255fd5">
					<Properties>
						<Font name="FontFace">
							<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
							<Weight>400</Weight>
							<Style>Normal</Style>
						</Font>
						<float name="LineHeight">1</float>
						<string name="LocalizationMatchIdentifier"></string>
						<string name="LocalizationMatchedSourceText"></string>
						<int name="MaxVisibleGraphemes">-1</int>
						<string name="OpenTypeFeatures"></string>
						<bool name="RichText">false</bool>
						<string name="Text">Model Response</string>
						<Color3 name="TextColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<token name="TextDirection">0</token>
						<bool name="TextScaled">false</bool>
						<float name="TextSize">14</float>
						<Color3 name="TextStrokeColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<float name="TextStrokeTransparency">1</float>
						<float name="TextTransparency">0</float>
						<token name="TextTruncate">0</token>
						<bool name="TextWrapped">true</bool>
						<token name="TextXAlignment">0</token>
						<token name="TextYAlignment">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0.5</X>
							<Y>0.5</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<float name="BackgroundTransparency">1</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0.5</XS>
							<XO>0</XO>
							<YS>0.5</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>0.899999976</XS>
							<XO>0</XO>
							<YS>0.949999988</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">1</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">ContentLabel</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
				</Item>
			</Item>
			<Item class="Frame" referent="RBX9d739d5cf6a64dd0b4ee98f4b84a6bf8">
				<Properties>
					<token name="Style">0</token>
					<bool name="Active">false</bool>
					<Vector2 name="AnchorPoint">
						<X>0.5</X>
						<Y>1</Y>
					</Vector2>
					<token name="AutomaticSize">0</token>
					<Color3 name="BackgroundColor3">
						<R>0.345098048</R>
						<G>0.427451015</G>
						<B>0.490196109</B>
					</Color3>
					<float name="BackgroundTransparency">1</float>
					<Color3 name="BorderColor3">
						<R>0</R>
						<G>0</G>
						<B>0</B>
					</Color3>
					<token name="BorderMode">0</token>
					<int name="BorderSizePixel">0</int>
					<bool name="ClipsDescendants">false</bool>
					<bool name="Draggable">false</bool>
					<bool name="Interactable">true</bool>
					<int name="LayoutOrder">0</int>
					<Ref name="NextSelectionDown">null</Ref>
					<Ref name="NextSelectionLeft">null</Ref>
					<Ref name="NextSelectionRight">null</Ref>
					<Ref name="NextSelectionUp">null</Ref>
					<UDim2 name="Position">
						<XS>0.5</XS>
						<XO>0</XO>
						<YS>0.221606731</YS>
						<YO>0</YO>
					</UDim2>
					<float name="Rotation">0</float>
					<bool name="Selectable">false</bool>
					<Ref name="SelectionImageObject">null</Ref>
					<int name="SelectionOrder">0</int>
					<token name="Sink">0</token>
					<UDim2 name="Size">
						<XS>0.850000083</XS>
						<XO>0</XO>
						<YS>0.141555712</YS>
						<YO>0</YO>
					</UDim2>
					<token name="SizeConstraint">0</token>
					<bool name="Visible">true</bool>
					<int name="ZIndex">1</int>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ModelThinkingFrame</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="Frame" referent="RBX71770093f40c4a3b961e16f47d3b69c3">
					<Properties>
						<token name="Style">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0</X>
							<Y>0</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>0.156862751</R>
							<G>0.156862751</G>
							<B>0.156862751</B>
						</Color3>
						<float name="BackgroundTransparency">0</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0</XS>
							<XO>0</XO>
							<YS>0</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>0.649999976</XS>
							<XO>0</XO>
							<YS>1</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">1</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">Bubble</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
					<Item class="UICorner" referent="RBXc8c6f96c7d054f0ebf9c9a32cb0b569a">
						<Properties>
							<UDim name="BottomLeftRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<UDim name="BottomRightRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<UDim name="TopLeftRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<UDim name="TopRightRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">UICorner</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextLabel" referent="RBXdf4e48aa3baf48448cc4637a1b0aaebb">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Model is thinking for</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.25</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>0.5</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.635996699</XS>
								<XO>0</XO>
								<YS>0.244562343</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.639432073</XS>
								<XO>0</XO>
								<YS>0.239124462</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">TaskNameLabel</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextLabel" referent="RBX9b22ce6e49c34416ad25651fe8f9863b">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">3 seconds</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.25</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>0.5</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.635996699</XS>
								<XO>0</XO>
								<YS>0.619992435</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.639432073</XS>
								<XO>0</XO>
								<YS>0.51173532</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">TimeLabel</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="ImageLabel" referent="RBX312b6ba13a584ef3b30737085fd5473a">
						<Properties>
							<Content name="Image"><url>rbxassetid://126455106069276</url></Content>
							<Color3 name="ImageColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<Vector2 name="ImageRectOffset">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<Vector2 name="ImageRectSize">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<float name="ImageTransparency">0.25</float>
							<token name="ResampleMode">0</token>
							<token name="ScaleType">3</token>
							<Rect2D name="SliceCenter">
								<min>
									<X>0</X>
									<Y>0</Y>
								</min>
								<max>
									<X>0</X>
									<Y>0</Y>
								</max>
							</Rect2D>
							<float name="SliceScale">1</float>
							<UDim2 name="TileSize">
								<XS>1</XS>
								<XO>0</XO>
								<YS>1</YS>
								<YO>0</YO>
							</UDim2>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0.5</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>1.83940596e-08</XS>
								<XO>0</XO>
								<YS>0.5</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.316280693</XS>
								<XO>0</XO>
								<YS>0.5</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">ImageLabel</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
				</Item>
			</Item>
			<Item class="Frame" referent="RBX1df7c999296e4409ade0625b5eb7dca6">
				<Properties>
					<token name="Style">0</token>
					<bool name="Active">false</bool>
					<Vector2 name="AnchorPoint">
						<X>0.5</X>
						<Y>1</Y>
					</Vector2>
					<token name="AutomaticSize">0</token>
					<Color3 name="BackgroundColor3">
						<R>0.345098048</R>
						<G>0.427451015</G>
						<B>0.490196109</B>
					</Color3>
					<float name="BackgroundTransparency">1</float>
					<Color3 name="BorderColor3">
						<R>0</R>
						<G>0</G>
						<B>0</B>
					</Color3>
					<token name="BorderMode">0</token>
					<int name="BorderSizePixel">0</int>
					<bool name="ClipsDescendants">false</bool>
					<bool name="Draggable">false</bool>
					<bool name="Interactable">true</bool>
					<int name="LayoutOrder">0</int>
					<Ref name="NextSelectionDown">null</Ref>
					<Ref name="NextSelectionLeft">null</Ref>
					<Ref name="NextSelectionRight">null</Ref>
					<Ref name="NextSelectionUp">null</Ref>
					<UDim2 name="Position">
						<XS>0.5</XS>
						<XO>0</XO>
						<YS>0.221606731</YS>
						<YO>0</YO>
					</UDim2>
					<float name="Rotation">0</float>
					<bool name="Selectable">false</bool>
					<Ref name="SelectionImageObject">null</Ref>
					<int name="SelectionOrder">0</int>
					<token name="Sink">0</token>
					<UDim2 name="Size">
						<XS>0.850000083</XS>
						<XO>0</XO>
						<YS>0.141555712</YS>
						<YO>0</YO>
					</UDim2>
					<token name="SizeConstraint">0</token>
					<bool name="Visible">true</bool>
					<int name="ZIndex">1</int>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ModelEditedFrame</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="Frame" referent="RBXbf61f4d6b3704e8fa8ddb8a2279260cf">
					<Properties>
						<token name="Style">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0</X>
							<Y>0</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>0.156862751</R>
							<G>0.156862751</G>
							<B>0.156862751</B>
						</Color3>
						<float name="BackgroundTransparency">0</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0</XS>
							<XO>0</XO>
							<YS>0</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>0.649999976</XS>
							<XO>0</XO>
							<YS>1</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">1</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">Bubble</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
					<Item class="UICorner" referent="RBXf420c82ec2be42dbace84d0b8d4d4416">
						<Properties>
							<UDim name="BottomLeftRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<UDim name="BottomRightRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<UDim name="TopLeftRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<UDim name="TopRightRadius">
								<S>0</S>
								<O>8</O>
							</UDim>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">UICorner</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextLabel" referent="RBX56c708795912409d818f4fe296f761ca">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Model edited your scripts.</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.25</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>0.5</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.635996699</XS>
								<XO>0</XO>
								<YS>0.244562343</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.639432073</XS>
								<XO>0</XO>
								<YS>0.239124462</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">TaskNameLabel</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="ImageLabel" referent="RBX83b5a4a0845b49eea7d5b8dee6ae662a">
						<Properties>
							<Content name="Image"><url>rbxassetid://80289912970625</url></Content>
							<Color3 name="ImageColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<Vector2 name="ImageRectOffset">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<Vector2 name="ImageRectSize">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<float name="ImageTransparency">0.25</float>
							<token name="ResampleMode">0</token>
							<token name="ScaleType">3</token>
							<Rect2D name="SliceCenter">
								<min>
									<X>0</X>
									<Y>0</Y>
								</min>
								<max>
									<X>0</X>
									<Y>0</Y>
								</max>
							</Rect2D>
							<float name="SliceScale">1</float>
							<UDim2 name="TileSize">
								<XS>1</XS>
								<XO>0</XO>
								<YS>1</YS>
								<YO>0</YO>
							</UDim2>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0.5</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>1.83940596e-08</XS>
								<XO>0</XO>
								<YS>0.5</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.316280693</XS>
								<XO>0</XO>
								<YS>0.5</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">ImageLabel</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextButton" referent="RBX7159f0c234c74d23a60b4525d30a445c">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Revert Changes</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">false</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">false</bool>
							<token name="TextXAlignment">2</token>
							<token name="TextYAlignment">1</token>
							<bool name="AutoButtonColor">true</bool>
							<Ref name="HoverHapticEffect">null</Ref>
							<bool name="Modal">false</bool>
							<Ref name="PressHapticEffect">null</Ref>
							<bool name="Selected">false</bool>
							<token name="Style">0</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.435294151</R>
								<G>0.239215702</G>
								<B>0.239215702</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.316280752</XS>
								<XO>0</XO>
								<YS>0.465525955</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">1</token>
							<UDim2 name="Size">
								<XS>0.649999976</XS>
								<XO>0</XO>
								<YS>0.349999994</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">RevertButton</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBX4e295be8f6dd46c2add31a912c061dd5">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
					<Item class="TextButton" referent="RBX2b8dd266e6b14d039e6837c79aa8bc34">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Accept AI Changes</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">false</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">false</bool>
							<token name="TextXAlignment">2</token>
							<token name="TextYAlignment">1</token>
							<bool name="AutoButtonColor">true</bool>
							<Ref name="HoverHapticEffect">null</Ref>
							<bool name="Modal">false</bool>
							<Ref name="PressHapticEffect">null</Ref>
							<bool name="Selected">false</bool>
							<token name="Style">0</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.321568638</R>
								<G>0.435294151</G>
								<B>0.235294133</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.316280752</XS>
								<XO>0</XO>
								<YS>0.465525955</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">1</token>
							<UDim2 name="Size">
								<XS>0.649999976</XS>
								<XO>0</XO>
								<YS>0.349999994</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">false</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">AcceptButton</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBXf1e5f299d01b4b8889770103a7564dd1">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
				</Item>
			</Item>
			<Item class="ScreenGui" referent="RBXc816fa38df32462c9c5bb8dad2804726">
				<Properties>
					<bool name="ClipToDeviceSafeArea">true</bool>
					<int name="DisplayOrder">0</int>
					<token name="SafeAreaCompatibility">1</token>
					<token name="ScreenInsets">2</token>
					<bool name="Enabled">true</bool>
					<bool name="ResetOnSpawn">true</bool>
					<token name="ZIndexBehavior">1</token>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">FeedbackGUI</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="Frame" referent="RBXf6b8c260d8644db5846968dbdf537881">
					<Properties>
						<token name="Style">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0</X>
							<Y>0</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>0.117647059</R>
							<G>0.117647059</G>
							<B>0.117647059</B>
						</Color3>
						<float name="BackgroundTransparency">0</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0</XS>
							<XO>0</XO>
							<YS>0</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>1</XS>
							<XO>0</XO>
							<YS>1</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">0</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">App</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
					<Item class="TextBox" referent="RBXc83a54ff63d2412ba3bb41461d85615f">
						<Properties>
							<bool name="ClearTextOnFocus">false</bool>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<bool name="MultiLine">true</bool>
							<string name="OpenTypeFeatures"></string>
							<Color3 name="PlaceholderColor3">
								<R>0.529411793</R>
								<G>0.529411793</G>
								<B>0.529411793</B>
							</Color3>
							<string name="PlaceholderText">Tell me bout your Vibe Coder expirience!</string>
							<bool name="RichText">false</bool>
							<bool name="ShowNativeInput">true</bool>
							<string name="Text"></string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextEditable">true</bool>
							<bool name="TextScaled">false</bool>
							<float name="TextSize">20</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.150000006</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">0</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.49955985</XS>
								<XO>0</XO>
								<YS>0.0386468396</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">1</token>
							<UDim2 name="Size">
								<XS>0.826584518</XS>
								<XO>0</XO>
								<YS>0.60202527</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">FeedbackInput</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextButton" referent="RBX4633cb1c01a9477d926ecf5a0f34ca6a">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Send</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">2</token>
							<token name="TextYAlignment">1</token>
							<bool name="AutoButtonColor">true</bool>
							<Ref name="HoverHapticEffect">null</Ref>
							<bool name="Modal">false</bool>
							<Ref name="PressHapticEffect">null</Ref>
							<bool name="Selected">false</bool>
							<token name="Style">0</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.258823544</R>
								<G>0.258823544</G>
								<B>0.258823544</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0862676054</XS>
								<XO>0</XO>
								<YS>0.832203388</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">1</token>
							<UDim2 name="Size">
								<XS>0.826584518</XS>
								<XO>0</XO>
								<YS>0.141525418</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">SendButton</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBX8be842b087564aa1b9a7c4b11a010dd9">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
					<Item class="TextLabel" referent="RBXf94c996cbcf74c69a5f7df7bd1883886">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">If you want me to contact you back, please leave your email in the feedback.</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">20</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.25</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0860000029</XS>
								<XO>0</XO>
								<YS>0.677053869</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.824852169</XS>
								<XO>1</XO>
								<YS>0.117847033</YS>
								<YO>1</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">TextLabel</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
				</Item>
			</Item>
			<Item class="ScreenGui" referent="RBXe874a4b71b38417ba50aa52466825579">
				<Properties>
					<bool name="ClipToDeviceSafeArea">true</bool>
					<int name="DisplayOrder">0</int>
					<token name="SafeAreaCompatibility">1</token>
					<token name="ScreenInsets">2</token>
					<bool name="Enabled">true</bool>
					<bool name="ResetOnSpawn">true</bool>
					<token name="ZIndexBehavior">1</token>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">WidgetGUI</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="Frame" referent="RBX79466bf5fc054037a18a5f0c2bcb0b56">
					<Properties>
						<token name="Style">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0</X>
							<Y>0</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>0.117647059</R>
							<G>0.117647059</G>
							<B>0.117647059</B>
						</Color3>
						<float name="BackgroundTransparency">0</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0</XS>
							<XO>0</XO>
							<YS>0</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>1</XS>
							<XO>0</XO>
							<YS>1</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">false</bool>
						<int name="ZIndex">10</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">NoSelectionFrame</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
					<Item class="Frame" referent="RBXd275311154a04e23b5a81ca3fb8e4100">
						<Properties>
							<token name="Style">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>0.5</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.5</XS>
								<XO>0</XO>
								<YS>0.5</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.5</XS>
								<XO>0</XO>
								<YS>0.150000006</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">11</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">Frame</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UIListLayout" referent="RBX50c8a9b1bf1d4b6b8c8bf1fae1eba2fc">
							<Properties>
								<token name="HorizontalFlex">0</token>
								<token name="ItemLineAlignment">0</token>
								<UDim name="Padding">
									<S>0</S>
									<O>0</O>
								</UDim>
								<token name="VerticalFlex">0</token>
								<bool name="Wraps">false</bool>
								<token name="FillDirection">1</token>
								<token name="HorizontalAlignment">1</token>
								<token name="SortOrder">2</token>
								<token name="VerticalAlignment">1</token>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UIListLayout</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="ImageLabel" referent="RBXc606f90a366a48638b7eb97b75c454b6">
							<Properties>
								<Content name="Image"><url>rbxassetid://79115352535620</url></Content>
								<Color3 name="ImageColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<Vector2 name="ImageRectOffset">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<Vector2 name="ImageRectSize">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<float name="ImageTransparency">0.25</float>
								<token name="ResampleMode">0</token>
								<token name="ScaleType">3</token>
								<Rect2D name="SliceCenter">
									<min>
										<X>0</X>
										<Y>0</Y>
									</min>
									<max>
										<X>0</X>
										<Y>0</Y>
									</max>
								</Rect2D>
								<float name="SliceScale">1</float>
								<UDim2 name="TileSize">
									<XS>1</XS>
									<XO>0</XO>
									<YS>1</YS>
									<YO>0</YO>
								</UDim2>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>0</XO>
									<YS>0</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>1</XS>
									<XO>0</XO>
									<YS>0.569999993</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">11</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ImageLabel</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextLabel" referent="RBX6f2191a2455742629c2f5d36b6a7e279">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">Select an script in Explorer first.</string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">true</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0.25</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>0</XO>
									<YS>0</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>1</XS>
									<XO>0</XO>
									<YS>0.5</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">11</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">TextLabel</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
					<Item class="TextLabel" referent="RBX8737af43f38442c99f9bd80851840b1c">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/GothamSSm.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
								<CachedFaceId><url>rbxasset://fonts/Montserrat-Regular.ttf</url></CachedFaceId>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Select a script to edit, or continue with Auto &#226;&#128;&#148; the agent can work across your place.</string>
							<Color3 name="TextColor3">
								<R>0.70588237</R>
								<G>0.70588237</G>
								<B>0.745098054</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">false</bool>
							<float name="TextSize">13</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">2</token>
							<token name="TextYAlignment">1</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.639215708</R>
								<G>0.635294139</G>
								<B>0.647058845</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0.105882354</R>
								<G>0.164705887</G>
								<B>0.20784314</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">1</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0500000007</XS>
								<XO>0</XO>
								<YS>0.620000005</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.899999976</XS>
								<XO>0</XO>
								<YS>0</YS>
								<YO>40</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">AutoHint</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextButton" referent="RBX041c61179a6e4561980e6845616dd1ea">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/GothamSSm.json</url></Family>
								<Weight>500</Weight>
								<Style>Normal</Style>
								<CachedFaceId><url>rbxasset://fonts/Montserrat-Medium.ttf</url></CachedFaceId>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Continue with Auto</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">false</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">false</bool>
							<token name="TextXAlignment">2</token>
							<token name="TextYAlignment">1</token>
							<bool name="AutoButtonColor">true</bool>
							<Ref name="HoverHapticEffect">null</Ref>
							<bool name="Modal">false</bool>
							<Ref name="PressHapticEffect">null</Ref>
							<bool name="Selected">false</bool>
							<token name="Style">0</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.215686277</R>
								<G>0.352941185</G>
								<B>0.627451003</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0.105882354</R>
								<G>0.164705887</G>
								<B>0.20784314</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.5</XS>
								<XO>-100</XO>
								<YS>0.720000029</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">1</token>
							<UDim2 name="Size">
								<XS>0</XS>
								<XO>200</XO>
								<YS>0</YS>
								<YO>36</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">ContinueAutoButton</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBXf5eaa290aef046a496f4738905e93d7c">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
				</Item>
				<Item class="Frame" referent="RBX7045cf97969e40f59f1c05c3dc523a59">
					<Properties>
						<token name="Style">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0</X>
							<Y>0</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>0.117647059</R>
							<G>0.117647059</G>
							<B>0.117647059</B>
						</Color3>
						<float name="BackgroundTransparency">0</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0</XS>
							<XO>0</XO>
							<YS>0</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>1</XS>
							<XO>0</XO>
							<YS>1</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">0</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">App</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
					<Item class="Frame" referent="RBXa9d7392588724502b24f2d04ab38a574">
						<Properties>
							<token name="Style">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>1</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.156862751</R>
								<G>0.156862751</G>
								<B>0.156862751</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.5</XS>
								<XO>0</XO>
								<YS>0.98999995</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.949999988</XS>
								<XO>0</XO>
								<YS>0.167168677</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">BottomThread</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBX6668196afba14e839ef143ace1763b85">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="Frame" referent="RBX1adf80642dbd45fc933b383055acc707">
							<Properties>
								<token name="Style">0</token>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>1</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>0.482352942</R>
									<G>0.541176498</G>
									<B>0.78039217</B>
								</Color3>
								<float name="BackgroundTransparency">0.899999976</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.256017506</XS>
									<XO>0</XO>
									<YS>0.220721155</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>0.480832011</XS>
									<XO>0</XO>
									<YS>0.154647633</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">false</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">SelectedScriptFrame</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="UICorner" referent="RBX47f538eb00cf400e9ffaf6fddef33364">
								<Properties>
									<UDim name="BottomLeftRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="BottomRightRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="TopLeftRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="TopRightRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">UICorner</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="TextLabel" referent="RBX3681183837044cfc84a14551ce6d477f">
								<Properties>
									<Font name="FontFace">
										<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
										<Weight>400</Weight>
										<Style>Normal</Style>
									</Font>
									<float name="LineHeight">1</float>
									<string name="LocalizationMatchIdentifier"></string>
									<string name="LocalizationMatchedSourceText"></string>
									<int name="MaxVisibleGraphemes">-1</int>
									<string name="OpenTypeFeatures"></string>
									<bool name="RichText">false</bool>
									<string name="Text">Script</string>
									<Color3 name="TextColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<token name="TextDirection">0</token>
									<bool name="TextScaled">true</bool>
									<float name="TextSize">18</float>
									<Color3 name="TextStrokeColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<float name="TextStrokeTransparency">1</float>
									<float name="TextTransparency">0.25</float>
									<token name="TextTruncate">0</token>
									<bool name="TextWrapped">true</bool>
									<token name="TextXAlignment">2</token>
									<token name="TextYAlignment">1</token>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0.5</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.520498514</XS>
										<XO>0</XO>
										<YS>0.499998957</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.685664654</XS>
										<XO>0</XO>
										<YS>0.899999976</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">1</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">ScriptTitle</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="ImageLabel" referent="RBX307aacb305854b2caed2a5ab8519ff9c">
								<Properties>
									<Content name="Image"><url>rbxassetid://113661567766482</url></Content>
									<Color3 name="ImageColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<Vector2 name="ImageRectOffset">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<Vector2 name="ImageRectSize">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<float name="ImageTransparency">0.25</float>
									<token name="ResampleMode">0</token>
									<token name="ScaleType">3</token>
									<Rect2D name="SliceCenter">
										<min>
											<X>0</X>
											<Y>0</Y>
										</min>
										<max>
											<X>0</X>
											<Y>0</Y>
										</max>
									</Rect2D>
									<float name="SliceScale">1</float>
									<UDim2 name="TileSize">
										<XS>1</XS>
										<XO>0</XO>
										<YS>1</YS>
										<YO>0</YO>
									</UDim2>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0</XS>
										<XO>3</XO>
										<YS>0</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.200000003</XS>
										<XO>0</XO>
										<YS>1</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">1</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">ScriptIcon</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
						<Item class="TextBox" referent="RBXd986341c822f471d9fd27b3cd6b63da4">
							<Properties>
								<bool name="ClearTextOnFocus">false</bool>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<bool name="MultiLine">true</bool>
								<string name="OpenTypeFeatures"></string>
								<Color3 name="PlaceholderColor3">
									<R>0.529411793</R>
									<G>0.529411793</G>
									<B>0.529411793</B>
								</Color3>
								<string name="PlaceholderText">Chat with Vibe Coder&#226;&#128;&#166; (@ to mention, Auto to edit the place)</string>
								<bool name="RichText">false</bool>
								<bool name="ShowNativeInput">true</bool>
								<string name="Text"></string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextEditable">true</bool>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0.150000006</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">0</token>
								<token name="TextYAlignment">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.497061342</XS>
									<XO>0</XO>
									<YS>0.299999893</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.944122851</XS>
									<XO>0</XO>
									<YS>0.41400972</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ChatInputTextBox</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="ImageButton" referent="RBX19e5d3ee4ded421ab50dae7a666853a6">
							<Properties>
								<Content name="HoverImage"><null></null></Content>
								<Content name="Image"><url>rbxassetid://123181546754641</url></Content>
								<Color3 name="ImageColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<Vector2 name="ImageRectOffset">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<Vector2 name="ImageRectSize">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<float name="ImageTransparency">0.25</float>
								<Content name="PressedImage"><null></null></Content>
								<token name="ResampleMode">0</token>
								<token name="ScaleType">3</token>
								<Rect2D name="SliceCenter">
									<min>
										<X>0</X>
										<Y>0</Y>
									</min>
									<max>
										<X>0</X>
										<Y>0</Y>
									</max>
								</Rect2D>
								<float name="SliceScale">1</float>
								<UDim2 name="TileSize">
									<XS>1</XS>
									<XO>0</XO>
									<YS>1</YS>
									<YO>0</YO>
								</UDim2>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.892009795</XS>
									<XO>0</XO>
									<YS>0.733529866</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.0900033265</XS>
									<XO>0</XO>
									<YS>0.160360187</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">SendButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextButton" referent="RBX022e432ad64b47cc8b7ab833677032cb">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/SourceSansPro.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
									<CachedFaceId><url>rbxasset://fonts/SourceSansPro-Regular.ttf</url></CachedFaceId>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text"></string>
								<Color3 name="TextColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">1</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">false</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>0.137254909</R>
									<G>0.137254909</G>
									<B>0.137254909</B>
								</Color3>
								<float name="BackgroundTransparency">0.899999976</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">1</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.0299999993</XS>
									<XO>0</XO>
									<YS>0.706502259</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.271118104</XS>
									<XO>0</XO>
									<YS>0.216216221</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">2</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">CurrentModelButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="UICorner" referent="RBXfd05056768784875a42b3db9b36aac73">
								<Properties>
									<UDim name="BottomLeftRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="BottomRightRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="TopLeftRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="TopRightRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">UICorner</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="ImageLabel" referent="RBX014c0a59646c42ba8e7f50f71c9fd197">
								<Properties>
									<Content name="Image"><url>rbxassetid://79274818810097</url></Content>
									<Color3 name="ImageColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<Vector2 name="ImageRectOffset">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<Vector2 name="ImageRectSize">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<float name="ImageTransparency">0.25</float>
									<token name="ResampleMode">0</token>
									<token name="ScaleType">3</token>
									<Rect2D name="SliceCenter">
										<min>
											<X>0</X>
											<Y>0</Y>
										</min>
										<max>
											<X>0</X>
											<Y>0</Y>
										</max>
									</Rect2D>
									<float name="SliceScale">1</float>
									<UDim2 name="TileSize">
										<XS>1</XS>
										<XO>0</XO>
										<YS>1</YS>
										<YO>0</YO>
									</UDim2>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.800000131</XS>
										<XO>0</XO>
										<YS>0.125</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.179667592</XS>
										<XO>0</XO>
										<YS>0.741667807</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">1</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">DropdownIcon</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="TextLabel" referent="RBX81a354b504cc44a1b6d499eb69afdc40">
								<Properties>
									<Font name="FontFace">
										<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
										<Weight>400</Weight>
										<Style>Normal</Style>
									</Font>
									<float name="LineHeight">1</float>
									<string name="LocalizationMatchIdentifier"></string>
									<string name="LocalizationMatchedSourceText"></string>
									<int name="MaxVisibleGraphemes">-1</int>
									<string name="OpenTypeFeatures"></string>
									<bool name="RichText">false</bool>
									<string name="Text">no model selected.</string>
									<Color3 name="TextColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<token name="TextDirection">0</token>
									<bool name="TextScaled">true</bool>
									<float name="TextSize">18</float>
									<Color3 name="TextStrokeColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<float name="TextStrokeTransparency">1</float>
									<float name="TextTransparency">0.25</float>
									<token name="TextTruncate">0</token>
									<bool name="TextWrapped">true</bool>
									<token name="TextXAlignment">0</token>
									<token name="TextYAlignment">1</token>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0.5</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.414509743</XS>
										<XO>0</XO>
										<YS>0.499999851</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.779018283</XS>
										<XO>0</XO>
										<YS>0.899999917</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">1</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">ModelTitle</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
						<Item class="TextBox" referent="RBX5e842e38469046c5a2b6adfd8a70e8c2">
							<Properties>
								<bool name="ClearTextOnFocus">false</bool>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<bool name="MultiLine">true</bool>
								<string name="OpenTypeFeatures"></string>
								<Color3 name="PlaceholderColor3">
									<R>0.529411793</R>
									<G>0.529411793</G>
									<B>0.529411793</B>
								</Color3>
								<string name="PlaceholderText">API key</string>
								<bool name="RichText">false</bool>
								<bool name="ShowNativeInput">true</bool>
								<string name="Text"></string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextEditable">true</bool>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0.150000006</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">0</token>
								<token name="TextYAlignment">1</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.678268731</XS>
									<XO>0</XO>
									<YS>0.733529329</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.287856996</XS>
									<XO>0</XO>
									<YS>0.151351243</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ApiKeyInput</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="ImageButton" referent="RBXc06f7b72283c470b9323bf60780a86c9">
							<Properties>
								<Content name="HoverImage"><null></null></Content>
								<Content name="Image"><url>rbxassetid://73515595170574</url></Content>
								<Color3 name="ImageColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<Vector2 name="ImageRectOffset">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<Vector2 name="ImageRectSize">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<float name="ImageTransparency">0.25</float>
								<Content name="PressedImage"><null></null></Content>
								<token name="ResampleMode">0</token>
								<token name="ScaleType">3</token>
								<Rect2D name="SliceCenter">
									<min>
										<X>0</X>
										<Y>0</Y>
									</min>
									<max>
										<X>0</X>
										<Y>0</Y>
									</max>
								</Rect2D>
								<float name="SliceScale">1</float>
								<UDim2 name="TileSize">
									<XS>1</XS>
									<XO>0</XO>
									<YS>1</YS>
									<YO>0</YO>
								</UDim2>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.819884002</XS>
									<XO>0</XO>
									<YS>0.733529747</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.0900033265</XS>
									<XO>0</XO>
									<YS>0.160360187</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ShowApiKeyButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextLabel" referent="RBXae81b915897146d79eb4e3ebe17a1d19">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">API KEY HIDDEN</string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">true</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0.25</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.677999973</XS>
									<XO>0</XO>
									<YS>0.734000027</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>0.287999988</XS>
									<XO>0</XO>
									<YS>0.150999993</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">false</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ApiKeyHiddenLabel</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="ImageButton" referent="RBXf4aa0a7989f34ef895117eedc7522843">
							<Properties>
								<Content name="HoverImage"><null></null></Content>
								<Content name="Image"><url>rbxassetid://130372484515289</url></Content>
								<Color3 name="ImageColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<Vector2 name="ImageRectOffset">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<Vector2 name="ImageRectSize">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<float name="ImageTransparency">0.25</float>
								<Content name="PressedImage"><null></null></Content>
								<token name="ResampleMode">0</token>
								<token name="ScaleType">3</token>
								<Rect2D name="SliceCenter">
									<min>
										<X>0</X>
										<Y>0</Y>
									</min>
									<max>
										<X>0</X>
										<Y>0</Y>
									</max>
								</Rect2D>
								<float name="SliceScale">1</float>
								<UDim2 name="TileSize">
									<XS>1</XS>
									<XO>0</XO>
									<YS>1</YS>
									<YO>0</YO>
								</UDim2>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.928200066</XS>
									<XO>0</XO>
									<YS>0.0738055855</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.0531407259</XS>
									<XO>0</XO>
									<YS>0.146914348</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">OpenMenuButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextButton" referent="RBX39991054f542484082522976aa59be77">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/GothamSSm.json</url></Family>
									<Weight>500</Weight>
									<Style>Normal</Style>
									<CachedFaceId><url>rbxasset://fonts/Montserrat-Medium.ttf</url></CachedFaceId>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">Stop</string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>0.862745106</G>
									<B>0.862745106</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">12</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">false</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>1</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>0.470588237</R>
									<G>0.156862751</G>
									<B>0.156862751</B>
								</Color3>
								<float name="BackgroundTransparency">0</float>
								<Color3 name="BorderColor3">
									<R>0.105882354</R>
									<G>0.164705887</G>
									<B>0.20784314</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>1</XS>
									<XO>-58</XO>
									<YS>0</YS>
									<YO>6</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0</XS>
									<XO>50</XO>
									<YS>0</YS>
									<YO>22</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">false</bool>
								<int name="ZIndex">5</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">StopButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="UICorner" referent="RBX0ea5221490ac48c290196bd128489f25">
								<Properties>
									<UDim name="BottomLeftRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="BottomRightRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="TopLeftRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="TopRightRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">UICorner</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
					</Item>
					<Item class="Frame" referent="RBX8f7ff9a40762420fb93a4de207a1142d">
						<Properties>
							<token name="Style">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>1</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.0980392173</R>
								<G>0.0980392173</G>
								<B>0.0980392173</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.274051219</XS>
								<XO>0</XO>
								<YS>0.940936327</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.440239549</XS>
								<XO>0</XO>
								<YS>0.220514685</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">false</bool>
							<int name="ZIndex">2</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">ModelSelectFrame</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBXb609b42c7c234c8e8b726a78a755e812">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextLabel" referent="RBX80d995c5722d49a79e987f6a02795b4c">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">Select AI Model</string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0.75</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">false</bool>
								<token name="TextXAlignment">0</token>
								<token name="TextYAlignment">1</token>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.363621145</XS>
									<XO>0</XO>
									<YS>0.014999954</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>0.677242219</XS>
									<XO>0</XO>
									<YS>0.129761562</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">2</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">Header</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="ScrollingFrame" referent="RBX2b86d187f26044fe89fb92051f371034">
							<Properties>
								<token name="AutomaticCanvasSize">2</token>
								<Content name="BottomImage"><url>rbxasset://textures/ui/Scroll/scroll-bottom.png</url></Content>
								<Vector2 name="CanvasPosition">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<UDim2 name="CanvasSize">
									<XS>0</XS>
									<XO>0</XO>
									<YS>0</YS>
									<YO>200</YO>
								</UDim2>
								<token name="ElasticBehavior">0</token>
								<token name="HorizontalScrollBarInset">0</token>
								<Content name="MidImage"><url>rbxasset://textures/ui/Scroll/scroll-middle.png</url></Content>
								<Color3 name="ScrollBarImageColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="ScrollBarImageTransparency">0</float>
								<int name="ScrollBarThickness">12</int>
								<token name="ScrollingDirection">2</token>
								<bool name="ScrollingEnabled">true</bool>
								<Content name="TopImage"><url>rbxasset://textures/ui/Scroll/scroll-top.png</url></Content>
								<token name="VerticalScrollBarInset">0</token>
								<token name="VerticalScrollBarPosition">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">true</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.5</XS>
									<XO>0</XO>
									<YS>0.185738772</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>0.949999928</XS>
									<XO>0</XO>
									<YS>0.814261019</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">2</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">true</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ModelsList</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="UIListLayout" referent="RBX31c11a7d434d44c0a455a4e2a4ef6af2">
								<Properties>
									<token name="HorizontalFlex">1</token>
									<token name="ItemLineAlignment">0</token>
									<UDim name="Padding">
										<S>0</S>
										<O>8</O>
									</UDim>
									<token name="VerticalFlex">0</token>
									<bool name="Wraps">false</bool>
									<token name="FillDirection">1</token>
									<token name="HorizontalAlignment">0</token>
									<token name="SortOrder">2</token>
									<token name="VerticalAlignment">1</token>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">UIListLayout</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="TextButton" referent="RBXd81a773af7974daea7cde74d6d845259">
								<Properties>
									<Font name="FontFace">
										<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
										<Weight>400</Weight>
										<Style>Normal</Style>
									</Font>
									<float name="LineHeight">1</float>
									<string name="LocalizationMatchIdentifier"></string>
									<string name="LocalizationMatchedSourceText"></string>
									<int name="MaxVisibleGraphemes">-1</int>
									<string name="OpenTypeFeatures"></string>
									<bool name="RichText">false</bool>
									<string name="Text">ModelName</string>
									<Color3 name="TextColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<token name="TextDirection">0</token>
									<bool name="TextScaled">true</bool>
									<float name="TextSize">14</float>
									<Color3 name="TextStrokeColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<float name="TextStrokeTransparency">1</float>
									<float name="TextTransparency">0.25</float>
									<token name="TextTruncate">0</token>
									<bool name="TextWrapped">true</bool>
									<token name="TextXAlignment">0</token>
									<token name="TextYAlignment">1</token>
									<bool name="AutoButtonColor">true</bool>
									<Ref name="HoverHapticEffect">null</Ref>
									<bool name="Modal">false</bool>
									<Ref name="PressHapticEffect">null</Ref>
									<bool name="Selected">false</bool>
									<token name="Style">0</token>
									<bool name="Active">true</bool>
									<Vector2 name="AnchorPoint">
										<X>0.5</X>
										<Y>0</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>0.0980392173</R>
										<G>0.0980392173</G>
										<B>0.0980392173</B>
									</Color3>
									<float name="BackgroundTransparency">0.899999976</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.0243607201</XS>
										<XO>0</XO>
										<YS>0.0309071168</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">true</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">1</token>
									<UDim2 name="Size">
										<XS>0.75</XS>
										<XO>0</XO>
										<YS>0</YS>
										<YO>20</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">false</bool>
									<int name="ZIndex">2</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">ModelSelectButton</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
								<Item class="UICorner" referent="RBX2a8fb8c6bf004999b5e0018a6f4562a5">
									<Properties>
										<UDim name="BottomLeftRadius">
											<S>0</S>
											<O>8</O>
										</UDim>
										<UDim name="BottomRightRadius">
											<S>0</S>
											<O>8</O>
										</UDim>
										<UDim name="TopLeftRadius">
											<S>0</S>
											<O>8</O>
										</UDim>
										<UDim name="TopRightRadius">
											<S>0</S>
											<O>8</O>
										</UDim>
										<BinaryString name="AttributesSerialize"></BinaryString>
										<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
										<bool name="DefinesCapabilities">false</bool>
										<string name="Name">UICorner</string>
										<int64 name="SourceAssetId">-1</int64>
										<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
									</Properties>
								</Item>
							</Item>
						</Item>
						<Item class="Frame" referent="RBXd6e8d61a472842798d0ae63afb22a6cf">
							<Properties>
								<token name="Style">0</token>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>0.678431392</R>
									<G>0.494117647</G>
									<B>0.956862748</B>
								</Color3>
								<float name="BackgroundTransparency">0</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.842000008</XS>
									<XO>0</XO>
									<YS>0.0149999997</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>0.211999997</XS>
									<XO>0</XO>
									<YS>0.129999995</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">2</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ProLabel</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="TextLabel" referent="RBX17cf5e1179994d7fa889441baf7af823">
								<Properties>
									<Font name="FontFace">
										<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
										<Weight>400</Weight>
										<Style>Normal</Style>
									</Font>
									<float name="LineHeight">1</float>
									<string name="LocalizationMatchIdentifier"></string>
									<string name="LocalizationMatchedSourceText"></string>
									<int name="MaxVisibleGraphemes">-1</int>
									<string name="OpenTypeFeatures"></string>
									<bool name="RichText">false</bool>
									<string name="Text">PRO</string>
									<Color3 name="TextColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<token name="TextDirection">0</token>
									<bool name="TextScaled">true</bool>
									<float name="TextSize">14</float>
									<Color3 name="TextStrokeColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<float name="TextStrokeTransparency">1</float>
									<float name="TextTransparency">0</float>
									<token name="TextTruncate">0</token>
									<bool name="TextWrapped">true</bool>
									<token name="TextXAlignment">2</token>
									<token name="TextYAlignment">1</token>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0.5</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>0.678431392</R>
										<G>0.494117647</G>
										<B>0.956862748</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.5</XS>
										<XO>0</XO>
										<YS>0.5</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>1</XS>
										<XO>0</XO>
										<YS>0.75</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">2</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">Text</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="UICorner" referent="RBX7888217b418c4313b417d748348c7480">
								<Properties>
									<UDim name="BottomLeftRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="BottomRightRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="TopLeftRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<UDim name="TopRightRadius">
										<S>0</S>
										<O>8</O>
									</UDim>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">UICorner</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
					</Item>
					<Item class="ScrollingFrame" referent="RBX84b62ade19fd46e5b224e8f9f441c986">
						<Properties>
							<token name="AutomaticCanvasSize">2</token>
							<Content name="BottomImage"><url>rbxasset://textures/ui/Scroll/scroll-bottom.png</url></Content>
							<Vector2 name="CanvasPosition">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<UDim2 name="CanvasSize">
								<XS>0</XS>
								<XO>0</XO>
								<YS>1</YS>
								<YO>0</YO>
							</UDim2>
							<token name="ElasticBehavior">0</token>
							<token name="HorizontalScrollBarInset">0</token>
							<Content name="MidImage"><url>rbxasset://textures/ui/Scroll/scroll-middle.png</url></Content>
							<Color3 name="ScrollBarImageColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="ScrollBarImageTransparency">1</float>
							<int name="ScrollBarThickness">12</int>
							<token name="ScrollingDirection">2</token>
							<bool name="ScrollingEnabled">true</bool>
							<Content name="TopImage"><url>rbxasset://textures/ui/Scroll/scroll-top.png</url></Content>
							<token name="VerticalScrollBarInset">0</token>
							<token name="VerticalScrollBarPosition">0</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">true</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.5</XS>
								<XO>0</XO>
								<YS>0.0546247326</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.949999928</XS>
								<XO>0</XO>
								<YS>0.756085217</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">true</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">ChatHistory</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UIListLayout" referent="RBXd945b1039ad84030bf62b33ba919522d">
							<Properties>
								<token name="HorizontalFlex">0</token>
								<token name="ItemLineAlignment">0</token>
								<UDim name="Padding">
									<S>0</S>
									<O>8</O>
								</UDim>
								<token name="VerticalFlex">0</token>
								<bool name="Wraps">false</bool>
								<token name="FillDirection">1</token>
								<token name="HorizontalAlignment">0</token>
								<token name="SortOrder">2</token>
								<token name="VerticalAlignment">1</token>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UIListLayout</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
					<Item class="Frame" referent="RBXfeae62613bf040ddac5882aa7ae20e3c">
						<Properties>
							<token name="Style">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>1</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.0980392173</R>
								<G>0.0980392173</G>
								<B>0.0980392173</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.753058791</XS>
								<XO>0</XO>
								<YS>0.81245333</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.440239578</XS>
								<XO>0</XO>
								<YS>0.155998558</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">false</bool>
							<int name="ZIndex">2</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">MenuFrame</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBXcb473ce32266426ca91f178960eab08a">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="UIListLayout" referent="RBX96987f665b064b9e92befde665f45209">
							<Properties>
								<token name="HorizontalFlex">0</token>
								<token name="ItemLineAlignment">0</token>
								<UDim name="Padding">
									<S>0</S>
									<O>0</O>
								</UDim>
								<token name="VerticalFlex">0</token>
								<bool name="Wraps">false</bool>
								<token name="FillDirection">1</token>
								<token name="HorizontalAlignment">0</token>
								<token name="SortOrder">2</token>
								<token name="VerticalAlignment">1</token>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UIListLayout</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextButton" referent="RBX5ccedc269cff400e9de00a0bd22c7334">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text"></string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">true</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>0</XO>
									<YS>0</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.899999976</XS>
									<XO>0</XO>
									<YS>0.330000013</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">3</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ClearButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="TextLabel" referent="RBX2a53a6d9b1c24ec5a2273f185b9e19ff">
								<Properties>
									<Font name="FontFace">
										<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
										<Weight>400</Weight>
										<Style>Normal</Style>
									</Font>
									<float name="LineHeight">1</float>
									<string name="LocalizationMatchIdentifier"></string>
									<string name="LocalizationMatchedSourceText"></string>
									<int name="MaxVisibleGraphemes">-1</int>
									<string name="OpenTypeFeatures"></string>
									<bool name="RichText">false</bool>
									<string name="Text">Clear chat</string>
									<Color3 name="TextColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<token name="TextDirection">1</token>
									<bool name="TextScaled">true</bool>
									<float name="TextSize">14</float>
									<Color3 name="TextStrokeColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<float name="TextStrokeTransparency">1</float>
									<float name="TextTransparency">0.25</float>
									<token name="TextTruncate">0</token>
									<bool name="TextWrapped">true</bool>
									<token name="TextXAlignment">0</token>
									<token name="TextYAlignment">1</token>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.184383377</XS>
										<XO>0</XO>
										<YS>0.499999672</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.815616727</XS>
										<XO>0</XO>
										<YS>0.75</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">3</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">TextLabel</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="ImageLabel" referent="RBX15947b78092c45a58cf825209dbdf921">
								<Properties>
									<Content name="Image"><url>rbxassetid://72456202240333</url></Content>
									<Color3 name="ImageColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<Vector2 name="ImageRectOffset">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<Vector2 name="ImageRectSize">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<float name="ImageTransparency">0.25</float>
									<token name="ResampleMode">0</token>
									<token name="ScaleType">3</token>
									<Rect2D name="SliceCenter">
										<min>
											<X>0</X>
											<Y>0</Y>
										</min>
										<max>
											<X>0</X>
											<Y>0</Y>
										</max>
									</Rect2D>
									<float name="SliceScale">1</float>
									<UDim2 name="TileSize">
										<XS>1</XS>
										<XO>0</XO>
										<YS>1</YS>
										<YO>0</YO>
									</UDim2>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0</XS>
										<XO>0</XO>
										<YS>0.5</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.200000003</XS>
										<XO>0</XO>
										<YS>0.5</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">3</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">ImageLabel</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
						<Item class="TextButton" referent="RBXb194ed0802ea4b0bab0f675df92ba6fd">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text"></string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">true</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>0</XO>
									<YS>0</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.899999976</XS>
									<XO>0</XO>
									<YS>0.330000013</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">3</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">FeedbackButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="TextLabel" referent="RBX926550ba3cfe4a23b7c6a06ce24cc18d">
								<Properties>
									<Font name="FontFace">
										<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
										<Weight>400</Weight>
										<Style>Normal</Style>
									</Font>
									<float name="LineHeight">1</float>
									<string name="LocalizationMatchIdentifier"></string>
									<string name="LocalizationMatchedSourceText"></string>
									<int name="MaxVisibleGraphemes">-1</int>
									<string name="OpenTypeFeatures"></string>
									<bool name="RichText">false</bool>
									<string name="Text">Send Feedback</string>
									<Color3 name="TextColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<token name="TextDirection">1</token>
									<bool name="TextScaled">true</bool>
									<float name="TextSize">14</float>
									<Color3 name="TextStrokeColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<float name="TextStrokeTransparency">1</float>
									<float name="TextTransparency">0.25</float>
									<token name="TextTruncate">0</token>
									<bool name="TextWrapped">true</bool>
									<token name="TextXAlignment">0</token>
									<token name="TextYAlignment">1</token>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.184383377</XS>
										<XO>0</XO>
										<YS>0.499999672</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.815616727</XS>
										<XO>0</XO>
										<YS>0.75</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">3</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">TextLabel</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="ImageLabel" referent="RBXd94f5ef7f56a45c9b349f098c624cf92">
								<Properties>
									<Content name="Image"><url>rbxassetid://90206302915644</url></Content>
									<Color3 name="ImageColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<Vector2 name="ImageRectOffset">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<Vector2 name="ImageRectSize">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<float name="ImageTransparency">0.25</float>
									<token name="ResampleMode">0</token>
									<token name="ScaleType">3</token>
									<Rect2D name="SliceCenter">
										<min>
											<X>0</X>
											<Y>0</Y>
										</min>
										<max>
											<X>0</X>
											<Y>0</Y>
										</max>
									</Rect2D>
									<float name="SliceScale">1</float>
									<UDim2 name="TileSize">
										<XS>1</XS>
										<XO>0</XO>
										<YS>1</YS>
										<YO>0</YO>
									</UDim2>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0</XS>
										<XO>0</XO>
										<YS>0.5</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.200000003</XS>
										<XO>0</XO>
										<YS>0.5</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">3</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">ImageLabel</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
						<Item class="TextButton" referent="RBXa7107c1afcbd48f588504cd7a6664557">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text"></string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">true</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>0</XO>
									<YS>0</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0.899999976</XS>
									<XO>0</XO>
									<YS>0.330000013</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">3</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">JoinSupportServerButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="TextLabel" referent="RBX05936a1ec6244c5fa3e87b6e8a35c314">
								<Properties>
									<Font name="FontFace">
										<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
										<Weight>400</Weight>
										<Style>Normal</Style>
									</Font>
									<float name="LineHeight">1</float>
									<string name="LocalizationMatchIdentifier"></string>
									<string name="LocalizationMatchedSourceText"></string>
									<int name="MaxVisibleGraphemes">-1</int>
									<string name="OpenTypeFeatures"></string>
									<bool name="RichText">false</bool>
									<string name="Text">Join Community Server</string>
									<Color3 name="TextColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<token name="TextDirection">1</token>
									<bool name="TextScaled">true</bool>
									<float name="TextSize">14</float>
									<Color3 name="TextStrokeColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<float name="TextStrokeTransparency">1</float>
									<float name="TextTransparency">0.25</float>
									<token name="TextTruncate">0</token>
									<bool name="TextWrapped">true</bool>
									<token name="TextXAlignment">0</token>
									<token name="TextYAlignment">1</token>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0.184383377</XS>
										<XO>0</XO>
										<YS>0.499999672</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.815616727</XS>
										<XO>0</XO>
										<YS>0.75</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">3</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">TextLabel</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
							<Item class="ImageLabel" referent="RBX823f8cd9028f40d6a9dd3137e6e61de2">
								<Properties>
									<Content name="Image"><url>rbxassetid://97572524929990</url></Content>
									<Color3 name="ImageColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<Vector2 name="ImageRectOffset">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<Vector2 name="ImageRectSize">
										<X>0</X>
										<Y>0</Y>
									</Vector2>
									<float name="ImageTransparency">0.25</float>
									<token name="ResampleMode">0</token>
									<token name="ScaleType">3</token>
									<Rect2D name="SliceCenter">
										<min>
											<X>0</X>
											<Y>0</Y>
										</min>
										<max>
											<X>0</X>
											<Y>0</Y>
										</max>
									</Rect2D>
									<float name="SliceScale">1</float>
									<UDim2 name="TileSize">
										<XS>1</XS>
										<XO>0</XO>
										<YS>1</YS>
										<YO>0</YO>
									</UDim2>
									<bool name="Active">false</bool>
									<Vector2 name="AnchorPoint">
										<X>0</X>
										<Y>0.5</Y>
									</Vector2>
									<token name="AutomaticSize">0</token>
									<Color3 name="BackgroundColor3">
										<R>1</R>
										<G>1</G>
										<B>1</B>
									</Color3>
									<float name="BackgroundTransparency">1</float>
									<Color3 name="BorderColor3">
										<R>0</R>
										<G>0</G>
										<B>0</B>
									</Color3>
									<token name="BorderMode">0</token>
									<int name="BorderSizePixel">0</int>
									<bool name="ClipsDescendants">false</bool>
									<bool name="Draggable">false</bool>
									<bool name="Interactable">true</bool>
									<int name="LayoutOrder">0</int>
									<Ref name="NextSelectionDown">null</Ref>
									<Ref name="NextSelectionLeft">null</Ref>
									<Ref name="NextSelectionRight">null</Ref>
									<Ref name="NextSelectionUp">null</Ref>
									<UDim2 name="Position">
										<XS>0</XS>
										<XO>0</XO>
										<YS>0.5</YS>
										<YO>0</YO>
									</UDim2>
									<float name="Rotation">0</float>
									<bool name="Selectable">false</bool>
									<Ref name="SelectionImageObject">null</Ref>
									<int name="SelectionOrder">0</int>
									<token name="Sink">0</token>
									<UDim2 name="Size">
										<XS>0.200000003</XS>
										<XO>0</XO>
										<YS>0.5</YS>
										<YO>0</YO>
									</UDim2>
									<token name="SizeConstraint">0</token>
									<bool name="Visible">true</bool>
									<int name="ZIndex">3</int>
									<bool name="AutoLocalize">true</bool>
									<Ref name="RootLocalizationTable">null</Ref>
									<token name="SelectionBehaviorDown">0</token>
									<token name="SelectionBehaviorLeft">0</token>
									<token name="SelectionBehaviorRight">0</token>
									<token name="SelectionBehaviorUp">0</token>
									<bool name="SelectionGroup">false</bool>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">ImageLabel</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
					</Item>
					<Item class="Frame" referent="RBXe88a9025bb564909b51c3c932acc1b6a">
						<Properties>
							<token name="Style">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0.5</X>
								<Y>1</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.403921574</R>
								<G>0.223529413</G>
								<B>0.223529413</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.5</XS>
								<XO>0</XO>
								<YS>0.80445838</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.949999988</XS>
								<XO>0</XO>
								<YS>0.0321747102</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">false</bool>
							<int name="ZIndex">1</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">WarningFrame</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBXe391738551d64462b34cd104ba2a2d9c">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextLabel" referent="RBX40a81d88b85147de984fef4bf72d18dc">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
									<Weight>400</Weight>
									<Style>Normal</Style>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">Warning</string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>0.956862807</G>
									<B>0.956862807</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">true</bool>
								<float name="TextSize">14</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">true</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0.5</X>
									<Y>0.5</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>0.913725555</G>
									<B>0.913725555</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0.5</XS>
									<XO>0</XO>
									<YS>0.5</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>0.75</XS>
									<XO>0</XO>
									<YS>0.800000012</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">WarningContent</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="ImageLabel" referent="RBXe1bc42f1327542a8a86c5406fcd10900">
							<Properties>
								<Content name="Image"><url>rbxassetid://106040231377035</url></Content>
								<Color3 name="ImageColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<Vector2 name="ImageRectOffset">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<Vector2 name="ImageRectSize">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<float name="ImageTransparency">0</float>
								<token name="ResampleMode">0</token>
								<token name="ScaleType">3</token>
								<Rect2D name="SliceCenter">
									<min>
										<X>0</X>
										<Y>0</Y>
									</min>
									<max>
										<X>0</X>
										<Y>0</Y>
									</max>
								</Rect2D>
								<float name="SliceScale">1</float>
								<UDim2 name="TileSize">
									<XS>1</XS>
									<XO>0</XO>
									<YS>1</YS>
									<YO>0</YO>
								</UDim2>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0.5</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>0</XO>
									<YS>0.5</YS>
									<YO>0</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>0.100000001</XS>
									<XO>0</XO>
									<YS>0.75</YS>
									<YO>0</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">ImageLabel</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
					<Item class="Frame" referent="RBX18cc688ad3804c65901ce05527b889ce">
						<Properties>
							<token name="Style">0</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.125490203</R>
								<G>0.141176477</G>
								<B>0.164705887</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0.105882354</R>
								<G>0.164705887</G>
								<B>0.20784314</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0</XS>
								<XO>8</XO>
								<YS>0</YS>
								<YO>8</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>1</XS>
								<XO>-16</XO>
								<YS>0</YS>
								<YO>72</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">false</bool>
							<int name="ZIndex">10</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">DiffReviewFrame</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBX627d579f81d241c7bc4586cd9221ab69">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextLabel" referent="RBX4cf7be5398c04c8daffd80cacdfd1343">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/GothamSSm.json</url></Family>
									<Weight>500</Weight>
									<Style>Normal</Style>
									<CachedFaceId><url>rbxasset://fonts/Montserrat-Medium.ttf</url></CachedFaceId>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">Pending edits: 0</string>
								<Color3 name="TextColor3">
									<R>0.90196079</R>
									<G>0.90196079</G>
									<B>0.941176474</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">13</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">false</bool>
								<token name="TextXAlignment">0</token>
								<token name="TextYAlignment">1</token>
								<bool name="Active">false</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>0.639215708</R>
									<G>0.635294139</G>
									<B>0.647058845</B>
								</Color3>
								<float name="BackgroundTransparency">1</float>
								<Color3 name="BorderColor3">
									<R>0.105882354</R>
									<G>0.164705887</G>
									<B>0.20784314</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">1</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>8</XO>
									<YS>0</YS>
									<YO>6</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">false</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">0</token>
								<UDim2 name="Size">
									<XS>1</XS>
									<XO>-16</XO>
									<YS>0</YS>
									<YO>22</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">Title</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
						<Item class="TextButton" referent="RBX7146612572a344dca0649acc850b31db">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/GothamSSm.json</url></Family>
									<Weight>500</Weight>
									<Style>Normal</Style>
									<CachedFaceId><url>rbxasset://fonts/Montserrat-Medium.ttf</url></CachedFaceId>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">Accept all</string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">12</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">false</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>0.156862751</R>
									<G>0.470588237</G>
									<B>0.274509817</B>
								</Color3>
								<float name="BackgroundTransparency">0</float>
								<Color3 name="BorderColor3">
									<R>0.105882354</R>
									<G>0.164705887</G>
									<B>0.20784314</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>8</XO>
									<YS>0</YS>
									<YO>36</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0</XS>
									<XO>90</XO>
									<YS>0</YS>
									<YO>26</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">AcceptAllButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="UICorner" referent="RBX30b149bc39e74bf8bcd579a0410b0e2c">
								<Properties>
									<UDim name="BottomLeftRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="BottomRightRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="TopLeftRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="TopRightRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">UICorner</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
						<Item class="TextButton" referent="RBX1097ee1be9b54880865edfc64db61b88">
							<Properties>
								<Font name="FontFace">
									<Family><url>rbxasset://fonts/families/GothamSSm.json</url></Family>
									<Weight>500</Weight>
									<Style>Normal</Style>
									<CachedFaceId><url>rbxasset://fonts/Montserrat-Medium.ttf</url></CachedFaceId>
								</Font>
								<float name="LineHeight">1</float>
								<string name="LocalizationMatchIdentifier"></string>
								<string name="LocalizationMatchedSourceText"></string>
								<int name="MaxVisibleGraphemes">-1</int>
								<string name="OpenTypeFeatures"></string>
								<bool name="RichText">false</bool>
								<string name="Text">Reject all</string>
								<Color3 name="TextColor3">
									<R>1</R>
									<G>1</G>
									<B>1</B>
								</Color3>
								<token name="TextDirection">0</token>
								<bool name="TextScaled">false</bool>
								<float name="TextSize">12</float>
								<Color3 name="TextStrokeColor3">
									<R>0</R>
									<G>0</G>
									<B>0</B>
								</Color3>
								<float name="TextStrokeTransparency">1</float>
								<float name="TextTransparency">0</float>
								<token name="TextTruncate">0</token>
								<bool name="TextWrapped">false</bool>
								<token name="TextXAlignment">2</token>
								<token name="TextYAlignment">1</token>
								<bool name="AutoButtonColor">true</bool>
								<Ref name="HoverHapticEffect">null</Ref>
								<bool name="Modal">false</bool>
								<Ref name="PressHapticEffect">null</Ref>
								<bool name="Selected">false</bool>
								<token name="Style">0</token>
								<bool name="Active">true</bool>
								<Vector2 name="AnchorPoint">
									<X>0</X>
									<Y>0</Y>
								</Vector2>
								<token name="AutomaticSize">0</token>
								<Color3 name="BackgroundColor3">
									<R>0.470588237</R>
									<G>0.196078435</G>
									<B>0.196078435</B>
								</Color3>
								<float name="BackgroundTransparency">0</float>
								<Color3 name="BorderColor3">
									<R>0.105882354</R>
									<G>0.164705887</G>
									<B>0.20784314</B>
								</Color3>
								<token name="BorderMode">0</token>
								<int name="BorderSizePixel">0</int>
								<bool name="ClipsDescendants">false</bool>
								<bool name="Draggable">false</bool>
								<bool name="Interactable">true</bool>
								<int name="LayoutOrder">0</int>
								<Ref name="NextSelectionDown">null</Ref>
								<Ref name="NextSelectionLeft">null</Ref>
								<Ref name="NextSelectionRight">null</Ref>
								<Ref name="NextSelectionUp">null</Ref>
								<UDim2 name="Position">
									<XS>0</XS>
									<XO>106</XO>
									<YS>0</YS>
									<YO>36</YO>
								</UDim2>
								<float name="Rotation">0</float>
								<bool name="Selectable">true</bool>
								<Ref name="SelectionImageObject">null</Ref>
								<int name="SelectionOrder">0</int>
								<token name="Sink">1</token>
								<UDim2 name="Size">
									<XS>0</XS>
									<XO>90</XO>
									<YS>0</YS>
									<YO>26</YO>
								</UDim2>
								<token name="SizeConstraint">0</token>
								<bool name="Visible">true</bool>
								<int name="ZIndex">1</int>
								<bool name="AutoLocalize">true</bool>
								<Ref name="RootLocalizationTable">null</Ref>
								<token name="SelectionBehaviorDown">0</token>
								<token name="SelectionBehaviorLeft">0</token>
								<token name="SelectionBehaviorRight">0</token>
								<token name="SelectionBehaviorUp">0</token>
								<bool name="SelectionGroup">false</bool>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">RejectAllButton</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
							<Item class="UICorner" referent="RBXea30c5c983ec40e49379a6b5977067d7">
								<Properties>
									<UDim name="BottomLeftRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="BottomRightRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="TopLeftRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<UDim name="TopRightRadius">
										<S>0</S>
										<O>6</O>
									</UDim>
									<BinaryString name="AttributesSerialize"></BinaryString>
									<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
									<bool name="DefinesCapabilities">false</bool>
									<string name="Name">UICorner</string>
									<int64 name="SourceAssetId">-1</int64>
									<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
								</Properties>
							</Item>
						</Item>
					</Item>
				</Item>
				<Item class="TextLabel" referent="RBX0879357763ef4902937ef03a42632cdb">
					<Properties>
						<Font name="FontFace">
							<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
							<Weight>400</Weight>
							<Style>Normal</Style>
						</Font>
						<float name="LineHeight">1</float>
						<string name="LocalizationMatchIdentifier"></string>
						<string name="LocalizationMatchedSourceText"></string>
						<int name="MaxVisibleGraphemes">-1</int>
						<string name="OpenTypeFeatures"></string>
						<bool name="RichText">false</bool>
						<string name="Text">Vibe Coder v1.0 &#226;&#128;&#148; just chat. Selection optional.</string>
						<Color3 name="TextColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<token name="TextDirection">0</token>
						<bool name="TextScaled">true</bool>
						<float name="TextSize">14</float>
						<Color3 name="TextStrokeColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<float name="TextStrokeTransparency">1</float>
						<float name="TextTransparency">0.25</float>
						<token name="TextTruncate">0</token>
						<bool name="TextWrapped">true</bool>
						<token name="TextXAlignment">2</token>
						<token name="TextYAlignment">1</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0.5</X>
							<Y>0</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<float name="BackgroundTransparency">1</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0.5</XS>
							<XO>0</XO>
							<YS>0.00903614424</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>0.899999976</XS>
							<XO>0</XO>
							<YS>0.0355421677</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">1</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">ReleaseInfo</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
				</Item>
				<Item class="Frame" referent="RBX9a1577f0854c48dc992d9b745e1def89">
					<Properties>
						<token name="Style">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0</X>
							<Y>0</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>0.117647059</R>
							<G>0.117647059</G>
							<B>0.117647059</B>
						</Color3>
						<float name="BackgroundTransparency">0</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0</XS>
							<XO>0</XO>
							<YS>0</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>1</XS>
							<XO>0</XO>
							<YS>1</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">8</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">BuyProFrame</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
					<Item class="ImageLabel" referent="RBX9e281a4a479046388a2a3858c45a2436">
						<Properties>
							<Content name="Image"><url>rbxassetid://115853486982676</url></Content>
							<Color3 name="ImageColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<Vector2 name="ImageRectOffset">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<Vector2 name="ImageRectSize">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<float name="ImageTransparency">0</float>
							<token name="ResampleMode">0</token>
							<token name="ScaleType">3</token>
							<Rect2D name="SliceCenter">
								<min>
									<X>0</X>
									<Y>0</Y>
								</min>
								<max>
									<X>0</X>
									<Y>0</Y>
								</max>
							</Rect2D>
							<float name="SliceScale">1</float>
							<UDim2 name="TileSize">
								<XS>1</XS>
								<XO>0</XO>
								<YS>1</YS>
								<YO>0</YO>
							</UDim2>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.222636372</XS>
								<XO>0</XO>
								<YS>0.0271084346</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.596456707</XS>
								<XO>0</XO>
								<YS>0.191987902</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">ImageLabel</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextLabel" referent="RBX476bf4f6d7c04d32929d1264f9217432">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">You have discovered a Vibe Coder PRO feature.</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">2</token>
							<token name="TextYAlignment">1</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0811600089</XS>
								<XO>0</XO>
								<YS>0.218373492</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.834194362</XS>
								<XO>0</XO>
								<YS>0.176204816</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">Header</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextLabel" referent="RBX816a41f07cf1469caf485d35a082cb93">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text"><![CDATA[With Vibe Coder PRO you can:

• Send unlimited messages.
• Use all available language models such as GPT-4o and Claude 4 Sonnet.
• Use 100% of AI's thinking power.]]></string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.25</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">1</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0850794911</XS>
								<XO>0</XO>
								<YS>0.409638554</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.868840098</XS>
								<XO>0</XO>
								<YS>0.213855416</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">Paragraph</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextLabel" referent="RBX51611ef1c8694ec78410f699d2a378b7">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">In order to unlock Vibe Coder PRO, buy T-Shirt that is available at the following link:</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.25</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">1</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0868525654</XS>
								<XO>0</XO>
								<YS>0.701807201</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.868840098</XS>
								<XO>0</XO>
								<YS>0.0542168692</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">Paragraph</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextBox" referent="RBXb86af38c24424ced92f8605cf282b283">
						<Properties>
							<bool name="ClearTextOnFocus">false</bool>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<bool name="MultiLine">false</bool>
							<string name="OpenTypeFeatures"></string>
							<Color3 name="PlaceholderColor3">
								<R>0.699999988</R>
								<G>0.699999988</G>
								<B>0.699999988</B>
							</Color3>
							<string name="PlaceholderText">NO LINK</string>
							<bool name="RichText">false</bool>
							<bool name="ShowNativeInput">true</bool>
							<string name="Text">https://www.roblox.com/catalog/79884753121491/Vibe-Coder-PRO</string>
							<Color3 name="TextColor3">
								<R>0.678431392</R>
								<G>0.494117677</G>
								<B>0.956862807</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextEditable">false</bool>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">2</token>
							<token name="TextYAlignment">1</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>0.156862751</R>
								<G>0.156862751</G>
								<B>0.156862751</B>
							</Color3>
							<float name="BackgroundTransparency">0</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0811600238</XS>
								<XO>0</XO>
								<YS>0.766566277</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">1</token>
							<UDim2 name="Size">
								<XS>0.834194362</XS>
								<XO>0</XO>
								<YS>0.0798192769</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">GamepassLinkInput</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
						<Item class="UICorner" referent="RBX8ff918e2b9954ff9b4c275be8dde7569">
							<Properties>
								<UDim name="BottomLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="BottomRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopLeftRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<UDim name="TopRightRadius">
									<S>0</S>
									<O>8</O>
								</UDim>
								<BinaryString name="AttributesSerialize"></BinaryString>
								<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
								<bool name="DefinesCapabilities">false</bool>
								<string name="Name">UICorner</string>
								<int64 name="SourceAssetId">-1</int64>
								<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
							</Properties>
						</Item>
					</Item>
					<Item class="TextLabel" referent="RBX40b26b9d4dea4690a6b71c3a8b02bfa1">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">Copy this link and paste it in your browser.</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.75</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">1</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0868525133</XS>
								<XO>0</XO>
								<YS>0.858433723</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.828041196</XS>
								<XO>0</XO>
								<YS>0.0180722885</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">Paragraph</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextLabel" referent="RBX1ecffd41d9e2487a9983e3a86aec6eee">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">IMPORTANT: Restart Roblox Studio after purchase.</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>0.674509823</G>
								<B>0.674509823</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>1</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.25</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">0</token>
							<token name="TextYAlignment">1</token>
							<bool name="Active">false</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.0868524835</XS>
								<XO>0</XO>
								<YS>0.885542154</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">false</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">0</token>
							<UDim2 name="Size">
								<XS>0.82850194</XS>
								<XO>0</XO>
								<YS>0.0223202705</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">Paragraph</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
					<Item class="TextButton" referent="RBXafaf8fe03694466383e6f251e04f40e1">
						<Properties>
							<Font name="FontFace">
								<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
								<Weight>400</Weight>
								<Style>Normal</Style>
							</Font>
							<float name="LineHeight">1</float>
							<string name="LocalizationMatchIdentifier"></string>
							<string name="LocalizationMatchedSourceText"></string>
							<int name="MaxVisibleGraphemes">-1</int>
							<string name="OpenTypeFeatures"></string>
							<bool name="RichText">false</bool>
							<string name="Text">I am not interested.</string>
							<Color3 name="TextColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<token name="TextDirection">0</token>
							<bool name="TextScaled">true</bool>
							<float name="TextSize">14</float>
							<Color3 name="TextStrokeColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<float name="TextStrokeTransparency">1</float>
							<float name="TextTransparency">0.75</float>
							<token name="TextTruncate">0</token>
							<bool name="TextWrapped">true</bool>
							<token name="TextXAlignment">1</token>
							<token name="TextYAlignment">1</token>
							<bool name="AutoButtonColor">true</bool>
							<Ref name="HoverHapticEffect">null</Ref>
							<bool name="Modal">false</bool>
							<Ref name="PressHapticEffect">null</Ref>
							<bool name="Selected">false</bool>
							<token name="Style">0</token>
							<bool name="Active">true</bool>
							<Vector2 name="AnchorPoint">
								<X>0</X>
								<Y>0</Y>
							</Vector2>
							<token name="AutomaticSize">0</token>
							<Color3 name="BackgroundColor3">
								<R>1</R>
								<G>1</G>
								<B>1</B>
							</Color3>
							<float name="BackgroundTransparency">1</float>
							<Color3 name="BorderColor3">
								<R>0</R>
								<G>0</G>
								<B>0</B>
							</Color3>
							<token name="BorderMode">0</token>
							<int name="BorderSizePixel">0</int>
							<bool name="ClipsDescendants">false</bool>
							<bool name="Draggable">false</bool>
							<bool name="Interactable">true</bool>
							<int name="LayoutOrder">0</int>
							<Ref name="NextSelectionDown">null</Ref>
							<Ref name="NextSelectionLeft">null</Ref>
							<Ref name="NextSelectionRight">null</Ref>
							<Ref name="NextSelectionUp">null</Ref>
							<UDim2 name="Position">
								<XS>0.549645364</XS>
								<XO>0</XO>
								<YS>0.959337354</YS>
								<YO>0</YO>
							</UDim2>
							<float name="Rotation">0</float>
							<bool name="Selectable">true</bool>
							<Ref name="SelectionImageObject">null</Ref>
							<int name="SelectionOrder">0</int>
							<token name="Sink">1</token>
							<UDim2 name="Size">
								<XS>0.365248233</XS>
								<XO>0</XO>
								<YS>0.0256024096</YS>
								<YO>0</YO>
							</UDim2>
							<token name="SizeConstraint">0</token>
							<bool name="Visible">true</bool>
							<int name="ZIndex">8</int>
							<bool name="AutoLocalize">true</bool>
							<Ref name="RootLocalizationTable">null</Ref>
							<token name="SelectionBehaviorDown">0</token>
							<token name="SelectionBehaviorLeft">0</token>
							<token name="SelectionBehaviorRight">0</token>
							<token name="SelectionBehaviorUp">0</token>
							<bool name="SelectionGroup">false</bool>
							<BinaryString name="AttributesSerialize"></BinaryString>
							<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
							<bool name="DefinesCapabilities">false</bool>
							<string name="Name">CloseButton</string>
							<int64 name="SourceAssetId">-1</int64>
							<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
						</Properties>
					</Item>
				</Item>
			</Item>
			<Item class="Frame" referent="RBX6ef91ba717e54d7db6cde81ed74a748f">
				<Properties>
					<token name="Style">0</token>
					<bool name="Active">false</bool>
					<Vector2 name="AnchorPoint">
						<X>0.5</X>
						<Y>1</Y>
					</Vector2>
					<token name="AutomaticSize">0</token>
					<Color3 name="BackgroundColor3">
						<R>0.345098048</R>
						<G>0.427451015</G>
						<B>0.490196109</B>
					</Color3>
					<float name="BackgroundTransparency">1</float>
					<Color3 name="BorderColor3">
						<R>0</R>
						<G>0</G>
						<B>0</B>
					</Color3>
					<token name="BorderMode">0</token>
					<int name="BorderSizePixel">0</int>
					<bool name="ClipsDescendants">false</bool>
					<bool name="Draggable">false</bool>
					<bool name="Interactable">true</bool>
					<int name="LayoutOrder">0</int>
					<Ref name="NextSelectionDown">null</Ref>
					<Ref name="NextSelectionLeft">null</Ref>
					<Ref name="NextSelectionRight">null</Ref>
					<Ref name="NextSelectionUp">null</Ref>
					<UDim2 name="Position">
						<XS>0.5</XS>
						<XO>0</XO>
						<YS>0.0624782071</YS>
						<YO>0</YO>
					</UDim2>
					<float name="Rotation">0</float>
					<bool name="Selectable">false</bool>
					<Ref name="SelectionImageObject">null</Ref>
					<int name="SelectionOrder">0</int>
					<token name="Sink">0</token>
					<UDim2 name="Size">
						<XS>0.850000024</XS>
						<XO>0</XO>
						<YS>0.25</YS>
						<YO>0</YO>
					</UDim2>
					<token name="SizeConstraint">0</token>
					<bool name="Visible">true</bool>
					<int name="ZIndex">1</int>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">SystemBubble</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="TextLabel" referent="RBXdf061510bfbd419392c38a2e48553277">
					<Properties>
						<Font name="FontFace">
							<Family><url>rbxasset://fonts/families/FredokaOne.json</url></Family>
							<Weight>400</Weight>
							<Style>Normal</Style>
						</Font>
						<float name="LineHeight">1</float>
						<string name="LocalizationMatchIdentifier"></string>
						<string name="LocalizationMatchedSourceText"></string>
						<int name="MaxVisibleGraphemes">-1</int>
						<string name="OpenTypeFeatures"></string>
						<bool name="RichText">false</bool>
						<string name="Text">System</string>
						<Color3 name="TextColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<token name="TextDirection">0</token>
						<bool name="TextScaled">false</bool>
						<float name="TextSize">14</float>
						<Color3 name="TextStrokeColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<float name="TextStrokeTransparency">1</float>
						<float name="TextTransparency">0.5</float>
						<token name="TextTruncate">0</token>
						<bool name="TextWrapped">true</bool>
						<token name="TextXAlignment">2</token>
						<token name="TextYAlignment">0</token>
						<bool name="Active">false</bool>
						<Vector2 name="AnchorPoint">
							<X>0.5</X>
							<Y>0.5</Y>
						</Vector2>
						<token name="AutomaticSize">0</token>
						<Color3 name="BackgroundColor3">
							<R>1</R>
							<G>1</G>
							<B>1</B>
						</Color3>
						<float name="BackgroundTransparency">1</float>
						<Color3 name="BorderColor3">
							<R>0</R>
							<G>0</G>
							<B>0</B>
						</Color3>
						<token name="BorderMode">0</token>
						<int name="BorderSizePixel">0</int>
						<bool name="ClipsDescendants">false</bool>
						<bool name="Draggable">false</bool>
						<bool name="Interactable">true</bool>
						<int name="LayoutOrder">0</int>
						<Ref name="NextSelectionDown">null</Ref>
						<Ref name="NextSelectionLeft">null</Ref>
						<Ref name="NextSelectionRight">null</Ref>
						<Ref name="NextSelectionUp">null</Ref>
						<UDim2 name="Position">
							<XS>0.5</XS>
							<XO>0</XO>
							<YS>0.5</YS>
							<YO>0</YO>
						</UDim2>
						<float name="Rotation">0</float>
						<bool name="Selectable">false</bool>
						<Ref name="SelectionImageObject">null</Ref>
						<int name="SelectionOrder">0</int>
						<token name="Sink">0</token>
						<UDim2 name="Size">
							<XS>0.899999976</XS>
							<XO>0</XO>
							<YS>0.949999988</YS>
							<YO>0</YO>
						</UDim2>
						<token name="SizeConstraint">0</token>
						<bool name="Visible">true</bool>
						<int name="ZIndex">1</int>
						<bool name="AutoLocalize">true</bool>
						<Ref name="RootLocalizationTable">null</Ref>
						<token name="SelectionBehaviorDown">0</token>
						<token name="SelectionBehaviorLeft">0</token>
						<token name="SelectionBehaviorRight">0</token>
						<token name="SelectionBehaviorUp">0</token>
						<bool name="SelectionGroup">false</bool>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">ContentLabel</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
				</Item>
			</Item>
		</Item>
		<Item class="Folder" referent="RBXfc2640a3045e44ee9af3536b6db60d21">
			<Properties>
				<Color3 name="IconTint">
					<R>0</R>
					<G>0</G>
					<B>0</B>
				</Color3>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">Libs</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
			<Item class="ModuleScript" referent="RBX60ad268a454c45bb80e064440d63495b">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[--------------------------------------------------------------------------------------------------------------------------
-- sha2.lua
--------------------------------------------------------------------------------------------------------------------------
-- VERSION: 12 (2022-02-23)
-- AUTHOR:  Egor Skriptunoff
-- LICENSE: MIT (the same license as Lua itself)
-- URL:     https://github.com/Egor-Skriptunoff/pure_lua_SHA
--
-- DESCRIPTION:
--    This module contains functions to calculate SHA digest:
--       MD5, SHA-1,
--       SHA-224, SHA-256, SHA-512/224, SHA-512/256, SHA-384, SHA-512,
--       SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256,
--       HMAC,
--       BLAKE2b, BLAKE2s, BLAKE2bp, BLAKE2sp, BLAKE2Xb, BLAKE2Xs,
--       BLAKE3, BLAKE3_KDF
--    Written in pure Lua.
--    Compatible with:
--       Lua 5.1, Lua 5.2, Lua 5.3, Lua 5.4, Fengari, LuaJIT 2.0/2.1 (any CPU endianness).
--    Main feature of this module: it was heavily optimized for speed.
--    For every Lua version the module contains particular implementation branch to get benefits from version-specific features.
--       - branch for Lua 5.1 (emulating bitwise operators using look-up table)
--       - branch for Lua 5.2 (using bit32/bit library), suitable for both Lua 5.2 with native "bit32" and Lua 5.1 with external library "bit"
--       - branch for Lua 5.3/5.4 (using native 64-bit bitwise operators)
--       - branch for Lua 5.3/5.4 (using native 32-bit bitwise operators) for Lua built with LUA_INT_TYPE=LUA_INT_INT
--       - branch for LuaJIT without FFI library (useful in a sandboxed environment)
--       - branch for LuaJIT x86 without FFI library (LuaJIT x86 has oddity because of lack of CPU registers)
--       - branch for LuaJIT 2.0 with FFI library (bit.* functions work only with Lua numbers)
--       - branch for LuaJIT 2.1 with FFI library (bit.* functions can work with "int64_t" arguments)
--
--
-- USAGE:
--    Input data should be provided as a binary string: either as a whole string or as a sequence of substrings (chunk-by-chunk loading, total length < 9*10^15 bytes).
--    Result (SHA digest) is returned in hexadecimal representation as a string of lowercase hex digits.
--    Simplest usage example:
--       local sha = require("sha2")
--       local your_hash = sha.sha256("your string")
--    See file "sha2_test.lua" for more examples.
--
--
-- CHANGELOG:
--  version     date      description
--  -------  ----------   -----------
--    12     2022-02-23   Now works in Luau (but NOT optimized for speed)
--    11     2022-01-09   BLAKE3 added
--    10     2022-01-02   BLAKE2 functions added
--     9     2020-05-10   Now works in OpenWrt's Lua (dialect of Lua 5.1 with "double" + "invisible int32")
--     8     2019-09-03   SHA-3 functions added
--     7     2019-03-17   Added functions to convert to/from base64
--     6     2018-11-12   HMAC added
--     5     2018-11-10   SHA-1 added
--     4     2018-11-03   MD5 added
--     3     2018-11-02   Bug fixed: incorrect hashing of long (2 GByte) data streams on Lua 5.3/5.4 built with "int32" integers
--     2     2018-10-07   Decreased module loading time in Lua 5.1 implementation branch (thanks to Peter Melnichenko for giving a hint)
--     1     2018-10-06   First release (only SHA-2 functions)
-----------------------------------------------------------------------------


local print_debug_messages = false  -- set to true to view some messages about your system's abilities and implementation branch chosen for your system

local unpack, table_concat, byte, char, string_rep, sub, gsub, gmatch, string_format, floor, ceil, math_min, math_max, tonumber, type, math_huge =
	table.unpack or unpack, table.concat, string.byte, string.char, string.rep, string.sub, string.gsub, string.gmatch, string.format, math.floor, math.ceil, math.min, math.max, tonumber, type, math.huge


--------------------------------------------------------------------------------
-- EXAMINING YOUR SYSTEM
--------------------------------------------------------------------------------

local function get_precision(one)
	-- "one" must be either float 1.0 or integer 1
	-- returns bits_precision, is_integer
	-- This function works correctly with all floating point datatypes (including non-IEEE-754)
	local k, n, m, prev_n = 0, one, one
	while true do
		k, prev_n, n, m = k + 1, n, n + n + 1, m + m + k % 2
		if k > 256 or n - (n - 1) ~= 1 or m - (m - 1) ~= 1 or n == m then
			return k, false   -- floating point datatype
		elseif n == prev_n then
			return k, true    -- integer datatype
		end
	end
end

-- Make sure Lua has "double" numbers
local x = 2/3
local Lua_has_double = x * 5 > 3 and x * 4 < 3 and get_precision(1.0) >= 53
assert(Lua_has_double, "at least 53-bit floating point numbers are required")

-- Q:
--    SHA2 was designed for FPU-less machines.
--    So, why floating point numbers are needed for this module?
-- A:
--    53-bit "double" numbers are useful to calculate "magic numbers" used in SHA.
--    I prefer to write 50 LOC "magic numbers calculator" instead of storing more than 200 constants explicitly in this source file.

local int_prec, Lua_has_integers = get_precision(1)
local Lua_has_int64 = Lua_has_integers and int_prec == 64
local Lua_has_int32 = Lua_has_integers and int_prec == 32
assert(Lua_has_int64 or Lua_has_int32 or not Lua_has_integers, "Lua integers must be either 32-bit or 64-bit")

-- Q:
--    Does it mean that almost all non-standard configurations are not supported?
-- A:
--    Yes.  Sorry, too many problems to support all possible Lua numbers configurations.
--       Lua 5.1/5.2    with "int32"               will not work.
--       Lua 5.1/5.2    with "int64"               will not work.
--       Lua 5.1/5.2    with "int128"              will not work.
--       Lua 5.1/5.2    with "float"               will not work.
--       Lua 5.1/5.2    with "double"              is OK.          (default config for Lua 5.1, Lua 5.2, LuaJIT)
--       Lua 5.3/5.4    with "int32"  + "float"    will not work.
--       Lua 5.3/5.4    with "int64"  + "float"    will not work.
--       Lua 5.3/5.4    with "int128" + "float"    will not work.
--       Lua 5.3/5.4    with "int32"  + "double"   is OK.          (config used by Fengari)
--       Lua 5.3/5.4    with "int64"  + "double"   is OK.          (default config for Lua 5.3, Lua 5.4)
--       Lua 5.3/5.4    with "int128" + "double"   will not work.
--   Using floating point numbers better than "double" instead of "double" is OK (non-IEEE-754 floating point implementation are allowed).
--   Using "int128" instead of "int64" is not OK: "int128" would require different branch of implementation for optimized SHA512.

-- Check for LuaJIT and 32-bit bitwise libraries
local is_LuaJIT = ({false, [1] = true})[1] and _VERSION ~= "Luau" and (type(jit) ~= "table" or jit.version_num >= 20000)  -- LuaJIT 1.x.x and Luau are treated as vanilla Lua 5.1/5.2
local is_LuaJIT_21  -- LuaJIT 2.1+
local LuaJIT_arch
local ffi           -- LuaJIT FFI library (as a table)
local b             -- 32-bit bitwise library (as a table)
local library_name

if is_LuaJIT then
	-- Assuming "bit" library is always available on LuaJIT
	b = require"bit"
	library_name = "bit"
	-- "ffi" is intentionally disabled on some systems for safety reason
	local LuaJIT_has_FFI, result = pcall(require, "ffi")
	if LuaJIT_has_FFI then
		ffi = result
	end
	is_LuaJIT_21 = not not loadstring"b=0b0"
	LuaJIT_arch = type(jit) == "table" and jit.arch or ffi and ffi.arch or nil
else
	-- For vanilla Lua, "bit"/"bit32" libraries are searched in global namespace only.  No attempt is made to load a library if it's not loaded yet.
	for _, libname in ipairs(_VERSION == "Lua 5.2" and {"bit32", "bit"} or {"bit", "bit32"}) do
		if type(_G[libname]) == "table" and _G[libname].bxor then
			b = _G[libname]
			library_name = libname
			break
		end
	end
end

--------------------------------------------------------------------------------
-- You can disable here some of your system's abilities (for testing purposes)
--------------------------------------------------------------------------------
-- is_LuaJIT = nil
-- is_LuaJIT_21 = nil
-- ffi = nil
-- Lua_has_int32 = nil
-- Lua_has_int64 = nil
-- b, library_name = nil
--------------------------------------------------------------------------------

if print_debug_messages then
	-- Printing list of abilities of your system
	print("Abilities:")
	print("   Lua version:               "..(is_LuaJIT and "LuaJIT "..(is_LuaJIT_21 and "2.1 " or "2.0 ")..(LuaJIT_arch or "")..(ffi and " with FFI" or " without FFI") or _VERSION))
	print("   Integer bitwise operators: "..(Lua_has_int64 and "int64" or Lua_has_int32 and "int32" or "no"))
	print("   32-bit bitwise library:    "..(library_name or "not found"))
end

-- Selecting the most suitable implementation for given set of abilities
local method, branch
if is_LuaJIT and ffi then
	method = "Using 'ffi' library of LuaJIT"
	branch = "FFI"
elseif is_LuaJIT then
	method = "Using special code for sandboxed LuaJIT (no FFI)"
	branch = "LJ"
elseif Lua_has_int64 then
	method = "Using native int64 bitwise operators"
	branch = "INT64"
elseif Lua_has_int32 then
	method = "Using native int32 bitwise operators"
	branch = "INT32"
elseif library_name then   -- when bitwise library is available (Lua 5.2 with native library "bit32" or Lua 5.1 with external library "bit")
	method = "Using '"..library_name.."' library"
	branch = "LIB32"
else
	method = "Emulating bitwise operators using look-up table"
	branch = "EMUL"
end

if print_debug_messages then
	-- Printing the implementation selected to be used on your system
	print("Implementation selected:")
	print("   "..method)
end


--------------------------------------------------------------------------------
-- BASIC 32-BIT BITWISE FUNCTIONS
--------------------------------------------------------------------------------

local AND, OR, XOR, SHL, SHR, ROL, ROR, NOT, NORM, HEX, XOR_BYTE
-- Only low 32 bits of function arguments matter, high bits are ignored
-- The result of all functions (except HEX) is an integer inside "correct range":
--    for "bit" library:    (-2^31)..(2^31-1)
--    for "bit32" library:        0..(2^32-1)

if branch == "FFI" or branch == "LJ" or branch == "LIB32" then

	-- Your system has 32-bit bitwise library (either "bit" or "bit32")

	AND  = b.band                -- 2 arguments
	OR   = b.bor                 -- 2 arguments
	XOR  = b.bxor                -- 2..5 arguments
	SHL  = b.lshift              -- second argument is integer 0..31
	SHR  = b.rshift              -- second argument is integer 0..31
	ROL  = b.rol or b.lrotate    -- second argument is integer 0..31
	ROR  = b.ror or b.rrotate    -- second argument is integer 0..31
	NOT  = b.bnot                -- only for LuaJIT
	NORM = b.tobit               -- only for LuaJIT
	HEX  = b.tohex               -- returns string of 8 lowercase hexadecimal digits
	assert(AND and OR and XOR and SHL and SHR and ROL and ROR and NOT, "Library '"..library_name.."' is incomplete")
	XOR_BYTE = XOR               -- XOR of two bytes (0..255)

elseif branch == "EMUL" then

	-- Emulating 32-bit bitwise operations using 53-bit floating point arithmetic

	function SHL(x, n)
		return (x * 2^n) % 2^32
	end

	function SHR(x, n)
		x = x % 2^32 / 2^n
		return x - x % 1
	end

	function ROL(x, n)
		x = x % 2^32 * 2^n
		local r = x % 2^32
		return r + (x - r) / 2^32
	end

	function ROR(x, n)
		x = x % 2^32 / 2^n
		local r = x % 1
		return r * 2^32 + (x - r)
	end

	local AND_of_two_bytes = {[0] = 0}  -- look-up table (256*256 entries)
	local idx = 0
	for y = 0, 127 * 256, 256 do
		for x = y, y + 127 do
			x = AND_of_two_bytes[x] * 2
			AND_of_two_bytes[idx] = x
			AND_of_two_bytes[idx + 1] = x
			AND_of_two_bytes[idx + 256] = x
			AND_of_two_bytes[idx + 257] = x + 1
			idx = idx + 2
		end
		idx = idx + 256
	end

	local function and_or_xor(x, y, operation)
		-- operation: nil = AND, 1 = OR, 2 = XOR
		local x0 = x % 2^32
		local y0 = y % 2^32
		local rx = x0 % 256
		local ry = y0 % 256
		local res = AND_of_two_bytes[rx + ry * 256]
		x = x0 - rx
		y = (y0 - ry) / 256
		rx = x % 65536
		ry = y % 256
		res = res + AND_of_two_bytes[rx + ry] * 256
		x = (x - rx) / 256
		y = (y - ry) / 256
		rx = x % 65536 + y % 256
		res = res + AND_of_two_bytes[rx] * 65536
		res = res + AND_of_two_bytes[(x + y - rx) / 256] * 16777216
		if operation then
			res = x0 + y0 - operation * res
		end
		return res
	end

	function AND(x, y)
		return and_or_xor(x, y)
	end

	function OR(x, y)
		return and_or_xor(x, y, 1)
	end

	function XOR(x, y, z, t, u)          -- 2..5 arguments
		if z then
			if t then
				if u then
					t = and_or_xor(t, u, 2)
				end
				z = and_or_xor(z, t, 2)
			end
			y = and_or_xor(y, z, 2)
		end
		return and_or_xor(x, y, 2)
	end

	function XOR_BYTE(x, y)
		return x + y - 2 * AND_of_two_bytes[x + y * 256]
	end

end

HEX = HEX
	or
	pcall(string_format, "%x", 2^31) and
	function (x)  -- returns string of 8 lowercase hexadecimal digits
		return string_format("%08x", x % 4294967296)
	end
	or
	function (x)  -- for OpenWrt's dialect of Lua
		return string_format("%08x", (x + 2^31) % 2^32 - 2^31)
	end

local function XORA5(x, y)
	return XOR(x, y or 0xA5A5A5A5) % 4294967296
end

local function create_array_of_lanes()
	return {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
end


--------------------------------------------------------------------------------
-- CREATING OPTIMIZED INNER LOOP
--------------------------------------------------------------------------------

-- Inner loop functions
local sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed, blake2s_feed_64, blake2b_feed_128, blake3_feed_64

-- Arrays of SHA-2 "magic numbers" (in "INT64" and "FFI" branches "*_lo" arrays contain 64-bit values)
local sha2_K_lo, sha2_K_hi, sha2_H_lo, sha2_H_hi, sha3_RC_lo, sha3_RC_hi = {}, {}, {}, {}, {}, {}
local sha2_H_ext256 = {[224] = {}, [256] = sha2_H_hi}
local sha2_H_ext512_lo, sha2_H_ext512_hi = {[384] = {}, [512] = sha2_H_lo}, {[384] = {}, [512] = sha2_H_hi}
local md5_K, md5_sha1_H = {}, {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}
local md5_next_shift = {0, 0, 0, 0, 0, 0, 0, 0, 28, 25, 26, 27, 0, 0, 10, 9, 11, 12, 0, 15, 16, 17, 18, 0, 20, 22, 23, 21}
local HEX64, lanes_index_base  -- defined only for branches that internally use 64-bit integers: "INT64" and "FFI"
local common_W = {}    -- temporary table shared between all calculations (to avoid creating new temporary table every time)
local common_W_blake2b, common_W_blake2s, v_for_blake2s_feed_64 = common_W, common_W, {}
local K_lo_modulo, hi_factor, hi_factor_keccak = 4294967296, 0, 0
local sigma = {
	{  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16 },
	{ 15, 11,  5,  9, 10, 16, 14,  7,  2, 13,  1,  3, 12,  8,  6,  4 },
	{ 12,  9, 13,  1,  6,  3, 16, 14, 11, 15,  4,  7,  8,  2, 10,  5 },
	{  8, 10,  4,  2, 14, 13, 12, 15,  3,  7,  6, 11,  5,  1, 16,  9 },
	{ 10,  1,  6,  8,  3,  5, 11, 16, 15,  2, 12, 13,  7,  9,  4, 14 },
	{  3, 13,  7, 11,  1, 12,  9,  4,  5, 14,  8,  6, 16, 15,  2, 10 },
	{ 13,  6,  2, 16, 15, 14,  5, 11,  1,  8,  7,  4, 10,  3,  9, 12 },
	{ 14, 12,  8, 15, 13,  2,  4, 10,  6,  1, 16,  5,  9,  7,  3, 11 },
	{  7, 16, 15, 10, 12,  4,  1,  9, 13,  3, 14,  8,  2,  5, 11,  6 },
	{ 11,  3,  9,  5,  8,  7,  2,  6, 16, 12, 10, 15,  4, 13, 14,  1 },
};  sigma[11], sigma[12] = sigma[1], sigma[2]
local perm_blake3 = {
	1, 3, 4, 11, 13, 10, 12, 6,
	1, 3, 4, 11, 13, 10,
	2, 7, 5, 8, 14, 15, 16, 9,
	2, 7, 5, 8, 14, 15,
}

local function build_keccak_format(elem)
	local keccak_format = {}
	for _, size in ipairs{1, 9, 13, 17, 18, 21} do
		keccak_format[size] = "<"..string_rep(elem, size)
	end
	return keccak_format
end


if branch == "FFI" then

	local common_W_FFI_int32 = ffi.new("int32_t[?]", 80)   -- 64 is enough for SHA256, but 80 is needed for SHA-1
	common_W_blake2s = common_W_FFI_int32
	v_for_blake2s_feed_64 = ffi.new("int32_t[?]", 16)
	perm_blake3 = ffi.new("uint8_t[?]", #perm_blake3 + 1, 0, unpack(perm_blake3))
	for j = 1, 10 do
		sigma[j] = ffi.new("uint8_t[?]", #sigma[j] + 1, 0, unpack(sigma[j]))
	end;  sigma[11], sigma[12] = sigma[1], sigma[2]


	-- SHA256 implementation for "LuaJIT with FFI" branch

	function sha256_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W, K = common_W_FFI_int32, sha2_K_hi
		for pos = offs, offs + size - 1, 64 do
			for j = 0, 15 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)   -- slow, but doesn't depend on endianness
				W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d)
			end
			for j = 16, 63 do
				local a, b = W[j-15], W[j-2]
				W[j] = NORM( XOR(ROR(a, 7), ROL(a, 14), SHR(a, 3)) + XOR(ROL(b, 15), ROL(b, 13), SHR(b, 10)) + W[j-7] + W[j-16] )
			end
			local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
			for j = 0, 63, 8 do  -- Thanks to Peter Cawley for this workaround (unroll the loop to avoid "PHI shuffling too complex" due to PHIs overlap)
				local z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j] + K[j+1] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+1] + K[j+2] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+2] + K[j+3] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+3] + K[j+4] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+4] + K[j+5] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+5] + K[j+6] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+6] + K[j+7] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(g, AND(e, XOR(f, g))) + XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + (W[j+7] + K[j+8] + h) )
				h, g, f, e = g, f, e, NORM( d + z )
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
			end
			H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4])
			H[5], H[6], H[7], H[8] = NORM(e + H[5]), NORM(f + H[6]), NORM(g + H[7]), NORM(h + H[8])
		end
	end


	local common_W_FFI_int64 = ffi.new("int64_t[?]", 80)
	common_W_blake2b = common_W_FFI_int64
	local int64 = ffi.typeof"int64_t"
	local int32 = ffi.typeof"int32_t"
	local uint32 = ffi.typeof"uint32_t"
	hi_factor = int64(2^32)

	if is_LuaJIT_21 then   -- LuaJIT 2.1 supports bitwise 64-bit operations

		local AND64, OR64, XOR64, NOT64, SHL64, SHR64, ROL64, ROR64  -- introducing synonyms for better code readability
			= AND,   OR,   XOR,   NOT,   SHL,   SHR,   ROL,   ROR
		HEX64 = HEX


		-- BLAKE2b implementation for "LuaJIT 2.1 + FFI" branch

		do
			local v = ffi.new("int64_t[?]", 16)
			local W = common_W_blake2b

			local function G(a, b, c, d, k1, k2)
				local va, vb, vc, vd = v[a], v[b], v[c], v[d]
				va = W[k1] + (va + vb)
				vd = ROR64(XOR64(vd, va), 32)
				vc = vc + vd
				vb = ROR64(XOR64(vb, vc), 24)
				va = W[k2] + (va + vb)
				vd = ROR64(XOR64(vd, va), 16)
				vc = vc + vd
				vb = ROL64(XOR64(vb, vc), 1)
				v[a], v[b], v[c], v[d] = va, vb, vc, vd
			end

			function blake2b_feed_128(H, _, str, offs, size, bytes_compressed, last_block_size, is_last_node)
				-- offs >= 0, size >= 0, size is multiple of 128
				local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
				for pos = offs, offs + size - 1, 128 do
					if str then
						for j = 1, 16 do
							pos = pos + 8
							local a, b, c, d, e, f, g, h = byte(str, pos - 7, pos)
							W[j] = XOR64(OR(SHL(h, 24), SHL(g, 16), SHL(f, 8), e) * int64(2^32), uint32(int32(OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a))))
						end
					end
					v[0x0], v[0x1], v[0x2], v[0x3], v[0x4], v[0x5], v[0x6], v[0x7] = h1, h2, h3, h4, h5, h6, h7, h8
					v[0x8], v[0x9], v[0xA], v[0xB], v[0xD], v[0xE], v[0xF] = sha2_H_lo[1], sha2_H_lo[2], sha2_H_lo[3], sha2_H_lo[4], sha2_H_lo[6], sha2_H_lo[7], sha2_H_lo[8]
					bytes_compressed = bytes_compressed + (last_block_size or 128)
					v[0xC] = XOR64(sha2_H_lo[5], bytes_compressed)  -- t0 = low_8_bytes(bytes_compressed)
					-- t1 = high_8_bytes(bytes_compressed) = 0,  message length is always below 2^53 bytes
					if last_block_size then  -- flag f0
						v[0xE] = NOT64(v[0xE])
					end
					if is_last_node then  -- flag f1
						v[0xF] = NOT64(v[0xF])
					end
					for j = 1, 12 do
						local row = sigma[j]
						G(0, 4,  8, 12, row[ 1], row[ 2])
						G(1, 5,  9, 13, row[ 3], row[ 4])
						G(2, 6, 10, 14, row[ 5], row[ 6])
						G(3, 7, 11, 15, row[ 7], row[ 8])
						G(0, 5, 10, 15, row[ 9], row[10])
						G(1, 6, 11, 12, row[11], row[12])
						G(2, 7,  8, 13, row[13], row[14])
						G(3, 4,  9, 14, row[15], row[16])
					end
					h1 = XOR64(h1, v[0x0], v[0x8])
					h2 = XOR64(h2, v[0x1], v[0x9])
					h3 = XOR64(h3, v[0x2], v[0xA])
					h4 = XOR64(h4, v[0x3], v[0xB])
					h5 = XOR64(h5, v[0x4], v[0xC])
					h6 = XOR64(h6, v[0x5], v[0xD])
					h7 = XOR64(h7, v[0x6], v[0xE])
					h8 = XOR64(h8, v[0x7], v[0xF])
				end
				H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
				return bytes_compressed
			end

		end


		-- SHA-3 implementation for "LuaJIT 2.1 + FFI" branch

		local arr64_t = ffi.typeof"int64_t[?]"
		-- lanes array is indexed from 0
		lanes_index_base = 0
		hi_factor_keccak = int64(2^32)

		function create_array_of_lanes()
			return arr64_t(30)  -- 25 + 5 for temporary usage
		end

		function keccak_feed(lanes, _, str, offs, size, block_size_in_bytes)
			-- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8
			local RC = sha3_RC_lo
			local qwords_qty = SHR(block_size_in_bytes, 3)
			for pos = offs, offs + size - 1, block_size_in_bytes do
				for j = 0, qwords_qty - 1 do
					pos = pos + 8
					local h, g, f, e, d, c, b, a = byte(str, pos - 7, pos)   -- slow, but doesn't depend on endianness
					lanes[j] = XOR64(lanes[j], OR64(OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) * int64(2^32), uint32(int32(OR(SHL(e, 24), SHL(f, 16), SHL(g, 8), h)))))
				end
				for round_idx = 1, 24 do
					for j = 0, 4 do
						lanes[25 + j] = XOR64(lanes[j], lanes[j+5], lanes[j+10], lanes[j+15], lanes[j+20])
					end
					local D = XOR64(lanes[25], ROL64(lanes[27], 1))
					lanes[1], lanes[6], lanes[11], lanes[16] = ROL64(XOR64(D, lanes[6]), 44), ROL64(XOR64(D, lanes[16]), 45), ROL64(XOR64(D, lanes[1]), 1), ROL64(XOR64(D, lanes[11]), 10)
					lanes[21] = ROL64(XOR64(D, lanes[21]), 2)
					D = XOR64(lanes[26], ROL64(lanes[28], 1))
					lanes[2], lanes[7], lanes[12], lanes[22] = ROL64(XOR64(D, lanes[12]), 43), ROL64(XOR64(D, lanes[22]), 61), ROL64(XOR64(D, lanes[7]), 6), ROL64(XOR64(D, lanes[2]), 62)
					lanes[17] = ROL64(XOR64(D, lanes[17]), 15)
					D = XOR64(lanes[27], ROL64(lanes[29], 1))
					lanes[3], lanes[8], lanes[18], lanes[23] = ROL64(XOR64(D, lanes[18]), 21), ROL64(XOR64(D, lanes[3]), 28), ROL64(XOR64(D, lanes[23]), 56), ROL64(XOR64(D, lanes[8]), 55)
					lanes[13] = ROL64(XOR64(D, lanes[13]), 25)
					D = XOR64(lanes[28], ROL64(lanes[25], 1))
					lanes[4], lanes[14], lanes[19], lanes[24] = ROL64(XOR64(D, lanes[24]), 14), ROL64(XOR64(D, lanes[19]), 8), ROL64(XOR64(D, lanes[4]), 27), ROL64(XOR64(D, lanes[14]), 39)
					lanes[9] = ROL64(XOR64(D, lanes[9]), 20)
					D = XOR64(lanes[29], ROL64(lanes[26], 1))
					lanes[5], lanes[10], lanes[15], lanes[20] = ROL64(XOR64(D, lanes[10]), 3), ROL64(XOR64(D, lanes[20]), 18), ROL64(XOR64(D, lanes[5]), 36), ROL64(XOR64(D, lanes[15]), 41)
					lanes[0] = XOR64(D, lanes[0])
					lanes[0], lanes[1], lanes[2], lanes[3], lanes[4] = XOR64(lanes[0], AND64(NOT64(lanes[1]), lanes[2]), RC[round_idx]), XOR64(lanes[1], AND64(NOT64(lanes[2]), lanes[3])), XOR64(lanes[2], AND64(NOT64(lanes[3]), lanes[4])), XOR64(lanes[3], AND64(NOT64(lanes[4]), lanes[0])), XOR64(lanes[4], AND64(NOT64(lanes[0]), lanes[1]))
					lanes[5], lanes[6], lanes[7], lanes[8], lanes[9] = XOR64(lanes[8], AND64(NOT64(lanes[9]), lanes[5])), XOR64(lanes[9], AND64(NOT64(lanes[5]), lanes[6])), XOR64(lanes[5], AND64(NOT64(lanes[6]), lanes[7])), XOR64(lanes[6], AND64(NOT64(lanes[7]), lanes[8])), XOR64(lanes[7], AND64(NOT64(lanes[8]), lanes[9]))
					lanes[10], lanes[11], lanes[12], lanes[13], lanes[14] = XOR64(lanes[11], AND64(NOT64(lanes[12]), lanes[13])), XOR64(lanes[12], AND64(NOT64(lanes[13]), lanes[14])), XOR64(lanes[13], AND64(NOT64(lanes[14]), lanes[10])), XOR64(lanes[14], AND64(NOT64(lanes[10]), lanes[11])), XOR64(lanes[10], AND64(NOT64(lanes[11]), lanes[12]))
					lanes[15], lanes[16], lanes[17], lanes[18], lanes[19] = XOR64(lanes[19], AND64(NOT64(lanes[15]), lanes[16])), XOR64(lanes[15], AND64(NOT64(lanes[16]), lanes[17])), XOR64(lanes[16], AND64(NOT64(lanes[17]), lanes[18])), XOR64(lanes[17], AND64(NOT64(lanes[18]), lanes[19])), XOR64(lanes[18], AND64(NOT64(lanes[19]), lanes[15]))
					lanes[20], lanes[21], lanes[22], lanes[23], lanes[24] = XOR64(lanes[22], AND64(NOT64(lanes[23]), lanes[24])), XOR64(lanes[23], AND64(NOT64(lanes[24]), lanes[20])), XOR64(lanes[24], AND64(NOT64(lanes[20]), lanes[21])), XOR64(lanes[20], AND64(NOT64(lanes[21]), lanes[22])), XOR64(lanes[21], AND64(NOT64(lanes[22]), lanes[23]))
				end
			end
		end


		local A5_long = 0xA5A5A5A5 * int64(2^32 + 1)  -- It's impossible to use constant 0xA5A5A5A5A5A5A5A5LL because it will raise syntax error on other Lua versions

		function XORA5(long, long2)
			return XOR64(long, long2 or A5_long)
		end


		-- SHA512 implementation for "LuaJIT 2.1 + FFI" branch

		function sha512_feed_128(H, _, str, offs, size)
			-- offs >= 0, size >= 0, size is multiple of 128
			local W, K = common_W_FFI_int64, sha2_K_lo
			for pos = offs, offs + size - 1, 128 do
				for j = 0, 15 do
					pos = pos + 8
					local a, b, c, d, e, f, g, h = byte(str, pos - 7, pos)   -- slow, but doesn't depend on endianness
					W[j] = OR64(OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) * int64(2^32), uint32(int32(OR(SHL(e, 24), SHL(f, 16), SHL(g, 8), h))))
				end
				for j = 16, 79 do
					local a, b = W[j-15], W[j-2]
					W[j] = XOR64(ROR64(a, 1), ROR64(a, 8), SHR64(a, 7)) + XOR64(ROR64(b, 19), ROL64(b, 3), SHR64(b, 6)) + W[j-7] + W[j-16]
				end
				local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
				for j = 0, 79, 8 do
					local z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+1] + W[j]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
					z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+2] + W[j+1]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
					z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+3] + W[j+2]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
					z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+4] + W[j+3]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
					z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+5] + W[j+4]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
					z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+6] + W[j+5]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
					z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+7] + W[j+6]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
					z = XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23)) + XOR64(g, AND64(e, XOR64(f, g))) + h + K[j+8] + W[j+7]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XOR64(AND64(XOR64(a, b), c), AND64(a, b)) + XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30)) + z
				end
				H[1] = a + H[1]
				H[2] = b + H[2]
				H[3] = c + H[3]
				H[4] = d + H[4]
				H[5] = e + H[5]
				H[6] = f + H[6]
				H[7] = g + H[7]
				H[8] = h + H[8]
			end
		end

	else  -- LuaJIT 2.0 doesn't support 64-bit bitwise operations

		local U = ffi.new("union{int64_t i64; struct{int32_t "..(ffi.abi("le") and "lo, hi" or "hi, lo")..";} i32;}[3]")
		-- this array of unions is used for fast splitting int64 into int32_high and int32_low

		-- "xorrific" 64-bit functions :-)
		-- int64 input is splitted into two int32 parts, some bitwise 32-bit operations are performed, finally the result is converted to int64
		-- these functions are needed because bit.* functions in LuaJIT 2.0 don't work with int64_t

		local function XORROR64_1(a)
			-- return XOR64(ROR64(a, 1), ROR64(a, 8), SHR64(a, 7))
			U[0].i64 = a
			local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi
			local t_lo = XOR(SHR(a_lo, 1), SHL(a_hi, 31), SHR(a_lo, 8), SHL(a_hi, 24), SHR(a_lo, 7), SHL(a_hi, 25))
			local t_hi = XOR(SHR(a_hi, 1), SHL(a_lo, 31), SHR(a_hi, 8), SHL(a_lo, 24), SHR(a_hi, 7))
			return t_hi * int64(2^32) + uint32(int32(t_lo))
		end

		local function XORROR64_2(b)
			-- return XOR64(ROR64(b, 19), ROL64(b, 3), SHR64(b, 6))
			U[0].i64 = b
			local b_lo, b_hi = U[0].i32.lo, U[0].i32.hi
			local u_lo = XOR(SHR(b_lo, 19), SHL(b_hi, 13), SHL(b_lo, 3), SHR(b_hi, 29), SHR(b_lo, 6), SHL(b_hi, 26))
			local u_hi = XOR(SHR(b_hi, 19), SHL(b_lo, 13), SHL(b_hi, 3), SHR(b_lo, 29), SHR(b_hi, 6))
			return u_hi * int64(2^32) + uint32(int32(u_lo))
		end

		local function XORROR64_3(e)
			-- return XOR64(ROR64(e, 14), ROR64(e, 18), ROL64(e, 23))
			U[0].i64 = e
			local e_lo, e_hi = U[0].i32.lo, U[0].i32.hi
			local u_lo = XOR(SHR(e_lo, 14), SHL(e_hi, 18), SHR(e_lo, 18), SHL(e_hi, 14), SHL(e_lo, 23), SHR(e_hi, 9))
			local u_hi = XOR(SHR(e_hi, 14), SHL(e_lo, 18), SHR(e_hi, 18), SHL(e_lo, 14), SHL(e_hi, 23), SHR(e_lo, 9))
			return u_hi * int64(2^32) + uint32(int32(u_lo))
		end

		local function XORROR64_6(a)
			-- return XOR64(ROR64(a, 28), ROL64(a, 25), ROL64(a, 30))
			U[0].i64 = a
			local b_lo, b_hi = U[0].i32.lo, U[0].i32.hi
			local u_lo = XOR(SHR(b_lo, 28), SHL(b_hi, 4), SHL(b_lo, 30), SHR(b_hi, 2), SHL(b_lo, 25), SHR(b_hi, 7))
			local u_hi = XOR(SHR(b_hi, 28), SHL(b_lo, 4), SHL(b_hi, 30), SHR(b_lo, 2), SHL(b_hi, 25), SHR(b_lo, 7))
			return u_hi * int64(2^32) + uint32(int32(u_lo))
		end

		local function XORROR64_4(e, f, g)
			-- return XOR64(g, AND64(e, XOR64(f, g)))
			U[0].i64 = f
			U[1].i64 = g
			U[2].i64 = e
			local f_lo, f_hi = U[0].i32.lo, U[0].i32.hi
			local g_lo, g_hi = U[1].i32.lo, U[1].i32.hi
			local e_lo, e_hi = U[2].i32.lo, U[2].i32.hi
			local result_lo = XOR(g_lo, AND(e_lo, XOR(f_lo, g_lo)))
			local result_hi = XOR(g_hi, AND(e_hi, XOR(f_hi, g_hi)))
			return result_hi * int64(2^32) + uint32(int32(result_lo))
		end

		local function XORROR64_5(a, b, c)
			-- return XOR64(AND64(XOR64(a, b), c), AND64(a, b))
			U[0].i64 = a
			U[1].i64 = b
			U[2].i64 = c
			local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi
			local b_lo, b_hi = U[1].i32.lo, U[1].i32.hi
			local c_lo, c_hi = U[2].i32.lo, U[2].i32.hi
			local result_lo = XOR(AND(XOR(a_lo, b_lo), c_lo), AND(a_lo, b_lo))
			local result_hi = XOR(AND(XOR(a_hi, b_hi), c_hi), AND(a_hi, b_hi))
			return result_hi * int64(2^32) + uint32(int32(result_lo))
		end

		local function XORROR64_7(a, b, m)
			-- return ROR64(XOR64(a, b), m), m = 1..31
			U[0].i64 = a
			U[1].i64 = b
			local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi
			local b_lo, b_hi = U[1].i32.lo, U[1].i32.hi
			local c_lo, c_hi = XOR(a_lo, b_lo), XOR(a_hi, b_hi)
			local t_lo = XOR(SHR(c_lo, m), SHL(c_hi, -m))
			local t_hi = XOR(SHR(c_hi, m), SHL(c_lo, -m))
			return t_hi * int64(2^32) + uint32(int32(t_lo))
		end

		local function XORROR64_8(a, b)
			-- return ROL64(XOR64(a, b), 1)
			U[0].i64 = a
			U[1].i64 = b
			local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi
			local b_lo, b_hi = U[1].i32.lo, U[1].i32.hi
			local c_lo, c_hi = XOR(a_lo, b_lo), XOR(a_hi, b_hi)
			local t_lo = XOR(SHL(c_lo, 1), SHR(c_hi, 31))
			local t_hi = XOR(SHL(c_hi, 1), SHR(c_lo, 31))
			return t_hi * int64(2^32) + uint32(int32(t_lo))
		end

		local function XORROR64_9(a, b)
			-- return ROR64(XOR64(a, b), 32)
			U[0].i64 = a
			U[1].i64 = b
			local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi
			local b_lo, b_hi = U[1].i32.lo, U[1].i32.hi
			local t_hi, t_lo = XOR(a_lo, b_lo), XOR(a_hi, b_hi)
			return t_hi * int64(2^32) + uint32(int32(t_lo))
		end

		local function XOR64(a, b)
			-- return XOR64(a, b)
			U[0].i64 = a
			U[1].i64 = b
			local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi
			local b_lo, b_hi = U[1].i32.lo, U[1].i32.hi
			local t_lo, t_hi = XOR(a_lo, b_lo), XOR(a_hi, b_hi)
			return t_hi * int64(2^32) + uint32(int32(t_lo))
		end

		local function XORROR64_11(a, b, c)
			-- return XOR64(a, b, c)
			U[0].i64 = a
			U[1].i64 = b
			U[2].i64 = c
			local a_lo, a_hi = U[0].i32.lo, U[0].i32.hi
			local b_lo, b_hi = U[1].i32.lo, U[1].i32.hi
			local c_lo, c_hi = U[2].i32.lo, U[2].i32.hi
			local t_lo, t_hi = XOR(a_lo, b_lo, c_lo), XOR(a_hi, b_hi, c_hi)
			return t_hi * int64(2^32) + uint32(int32(t_lo))
		end

		function XORA5(long, long2)
			-- return XOR64(long, long2 or 0xA5A5A5A5A5A5A5A5)
			U[0].i64 = long
			local lo32, hi32 = U[0].i32.lo, U[0].i32.hi
			local long2_lo, long2_hi = 0xA5A5A5A5, 0xA5A5A5A5
			if long2 then
				U[1].i64 = long2
				long2_lo, long2_hi = U[1].i32.lo, U[1].i32.hi
			end
			lo32 = XOR(lo32, long2_lo)
			hi32 = XOR(hi32, long2_hi)
			return hi32 * int64(2^32) + uint32(int32(lo32))
		end

		function HEX64(long)
			U[0].i64 = long
			return HEX(U[0].i32.hi)..HEX(U[0].i32.lo)
		end


		-- SHA512 implementation for "LuaJIT 2.0 + FFI" branch

		function sha512_feed_128(H, _, str, offs, size)
			-- offs >= 0, size >= 0, size is multiple of 128
			local W, K = common_W_FFI_int64, sha2_K_lo
			for pos = offs, offs + size - 1, 128 do
				for j = 0, 15 do
					pos = pos + 8
					local a, b, c, d, e, f, g, h = byte(str, pos - 7, pos)   -- slow, but doesn't depend on endianness
					W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d) * int64(2^32) + uint32(int32(OR(SHL(e, 24), SHL(f, 16), SHL(g, 8), h)))
				end
				for j = 16, 79 do
					W[j] = XORROR64_1(W[j-15]) + XORROR64_2(W[j-2]) + W[j-7] + W[j-16]
				end
				local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
				for j = 0, 79, 8 do
					local z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+1] + W[j]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
					z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+2] + W[j+1]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
					z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+3] + W[j+2]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
					z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+4] + W[j+3]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
					z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+5] + W[j+4]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
					z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+6] + W[j+5]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
					z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+7] + W[j+6]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
					z = XORROR64_3(e) + XORROR64_4(e, f, g) + h + K[j+8] + W[j+7]
					h, g, f, e = g, f, e, z + d
					d, c, b, a = c, b, a, XORROR64_5(a, b, c) + XORROR64_6(a) + z
				end
				H[1] = a + H[1]
				H[2] = b + H[2]
				H[3] = c + H[3]
				H[4] = d + H[4]
				H[5] = e + H[5]
				H[6] = f + H[6]
				H[7] = g + H[7]
				H[8] = h + H[8]
			end
		end


		-- BLAKE2b implementation for "LuaJIT 2.0 + FFI" branch

		do
			local v = ffi.new("int64_t[?]", 16)
			local W = common_W_blake2b

			local function G(a, b, c, d, k1, k2)
				local va, vb, vc, vd = v[a], v[b], v[c], v[d]
				va = W[k1] + (va + vb)
				vd = XORROR64_9(vd, va)
				vc = vc + vd
				vb = XORROR64_7(vb, vc, 24)
				va = W[k2] + (va + vb)
				vd = XORROR64_7(vd, va, 16)
				vc = vc + vd
				vb = XORROR64_8(vb, vc)
				v[a], v[b], v[c], v[d] = va, vb, vc, vd
			end

			function blake2b_feed_128(H, _, str, offs, size, bytes_compressed, last_block_size, is_last_node)
				-- offs >= 0, size >= 0, size is multiple of 128
				local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
				for pos = offs, offs + size - 1, 128 do
					if str then
						for j = 1, 16 do
							pos = pos + 8
							local a, b, c, d, e, f, g, h = byte(str, pos - 7, pos)
							W[j] = XOR64(OR(SHL(h, 24), SHL(g, 16), SHL(f, 8), e) * int64(2^32), uint32(int32(OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a))))
						end
					end
					v[0x0], v[0x1], v[0x2], v[0x3], v[0x4], v[0x5], v[0x6], v[0x7] = h1, h2, h3, h4, h5, h6, h7, h8
					v[0x8], v[0x9], v[0xA], v[0xB], v[0xD], v[0xE], v[0xF] = sha2_H_lo[1], sha2_H_lo[2], sha2_H_lo[3], sha2_H_lo[4], sha2_H_lo[6], sha2_H_lo[7], sha2_H_lo[8]
					bytes_compressed = bytes_compressed + (last_block_size or 128)
					v[0xC] = XOR64(sha2_H_lo[5], bytes_compressed)  -- t0 = low_8_bytes(bytes_compressed)
					-- t1 = high_8_bytes(bytes_compressed) = 0,  message length is always below 2^53 bytes
					if last_block_size then  -- flag f0
						v[0xE] = -1 - v[0xE]
					end
					if is_last_node then  -- flag f1
						v[0xF] = -1 - v[0xF]
					end
					for j = 1, 12 do
						local row = sigma[j]
						G(0, 4,  8, 12, row[ 1], row[ 2])
						G(1, 5,  9, 13, row[ 3], row[ 4])
						G(2, 6, 10, 14, row[ 5], row[ 6])
						G(3, 7, 11, 15, row[ 7], row[ 8])
						G(0, 5, 10, 15, row[ 9], row[10])
						G(1, 6, 11, 12, row[11], row[12])
						G(2, 7,  8, 13, row[13], row[14])
						G(3, 4,  9, 14, row[15], row[16])
					end
					h1 = XORROR64_11(h1, v[0x0], v[0x8])
					h2 = XORROR64_11(h2, v[0x1], v[0x9])
					h3 = XORROR64_11(h3, v[0x2], v[0xA])
					h4 = XORROR64_11(h4, v[0x3], v[0xB])
					h5 = XORROR64_11(h5, v[0x4], v[0xC])
					h6 = XORROR64_11(h6, v[0x5], v[0xD])
					h7 = XORROR64_11(h7, v[0x6], v[0xE])
					h8 = XORROR64_11(h8, v[0x7], v[0xF])
				end
				H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
				return bytes_compressed
			end

		end

	end


	-- MD5 implementation for "LuaJIT with FFI" branch

	function md5_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W, K = common_W_FFI_int32, md5_K
		for pos = offs, offs + size - 1, 64 do
			for j = 0, 15 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)   -- slow, but doesn't depend on endianness
				W[j] = OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a)
			end
			local a, b, c, d = H[1], H[2], H[3], H[4]
			for j = 0, 15, 4 do
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+1] + W[j  ] + a),  7) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+2] + W[j+1] + a), 12) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+3] + W[j+2] + a), 17) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+4] + W[j+3] + a), 22) + b)
			end
			for j = 16, 31, 4 do
				local g = 5*j
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+1] + W[AND(g + 1, 15)] + a),  5) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+2] + W[AND(g + 6, 15)] + a),  9) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+3] + W[AND(g - 5, 15)] + a), 14) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+4] + W[AND(g    , 15)] + a), 20) + b)
			end
			for j = 32, 47, 4 do
				local g = 3*j
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+1] + W[AND(g + 5, 15)] + a),  4) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+2] + W[AND(g + 8, 15)] + a), 11) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+3] + W[AND(g - 5, 15)] + a), 16) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+4] + W[AND(g - 2, 15)] + a), 23) + b)
			end
			for j = 48, 63, 4 do
				local g = 7*j
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+1] + W[AND(g    , 15)] + a),  6) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+2] + W[AND(g + 7, 15)] + a), 10) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+3] + W[AND(g - 2, 15)] + a), 15) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+4] + W[AND(g + 5, 15)] + a), 21) + b)
			end
			H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4])
		end
	end


	-- SHA-1 implementation for "LuaJIT with FFI" branch

	function sha1_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W = common_W_FFI_int32
		for pos = offs, offs + size - 1, 64 do
			for j = 0, 15 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)   -- slow, but doesn't depend on endianness
				W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d)
			end
			for j = 16, 79 do
				W[j] = ROL(XOR(W[j-3], W[j-8], W[j-14], W[j-16]), 1)
			end
			local a, b, c, d, e = H[1], H[2], H[3], H[4], H[5]
			for j = 0, 19, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j]   + 0x5A827999 + e))          -- constant = floor(2^30 * sqrt(2))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+1] + 0x5A827999 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+2] + 0x5A827999 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+3] + 0x5A827999 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+4] + 0x5A827999 + e))
			end
			for j = 20, 39, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j]   + 0x6ED9EBA1 + e))                       -- 2^30 * sqrt(3)
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0x6ED9EBA1 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0x6ED9EBA1 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0x6ED9EBA1 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0x6ED9EBA1 + e))
			end
			for j = 40, 59, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j]   + 0x8F1BBCDC + e))  -- 2^30 * sqrt(5)
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+1] + 0x8F1BBCDC + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+2] + 0x8F1BBCDC + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+3] + 0x8F1BBCDC + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+4] + 0x8F1BBCDC + e))
			end
			for j = 60, 79, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j]   + 0xCA62C1D6 + e))                       -- 2^30 * sqrt(10)
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0xCA62C1D6 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0xCA62C1D6 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0xCA62C1D6 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0xCA62C1D6 + e))
			end
			H[1], H[2], H[3], H[4], H[5] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]), NORM(e + H[5])
		end
	end

end


if branch == "FFI" and not is_LuaJIT_21 or branch == "LJ" then

	if branch == "FFI" then
		local arr32_t = ffi.typeof"int32_t[?]"

		function create_array_of_lanes()
			return arr32_t(31)  -- 25 + 5 + 1 (due to 1-based indexing)
		end

	end


	-- SHA-3 implementation for "LuaJIT 2.0 + FFI" and "LuaJIT without FFI" branches

	function keccak_feed(lanes_lo, lanes_hi, str, offs, size, block_size_in_bytes)
		-- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8
		local RC_lo, RC_hi = sha3_RC_lo, sha3_RC_hi
		local qwords_qty = SHR(block_size_in_bytes, 3)
		for pos = offs, offs + size - 1, block_size_in_bytes do
			for j = 1, qwords_qty do
				local a, b, c, d = byte(str, pos + 1, pos + 4)
				lanes_lo[j] = XOR(lanes_lo[j], OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a))
				pos = pos + 8
				a, b, c, d = byte(str, pos - 3, pos)
				lanes_hi[j] = XOR(lanes_hi[j], OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a))
			end
			for round_idx = 1, 24 do
				for j = 1, 5 do
					lanes_lo[25 + j] = XOR(lanes_lo[j], lanes_lo[j + 5], lanes_lo[j + 10], lanes_lo[j + 15], lanes_lo[j + 20])
				end
				for j = 1, 5 do
					lanes_hi[25 + j] = XOR(lanes_hi[j], lanes_hi[j + 5], lanes_hi[j + 10], lanes_hi[j + 15], lanes_hi[j + 20])
				end
				local D_lo = XOR(lanes_lo[26], SHL(lanes_lo[28], 1), SHR(lanes_hi[28], 31))
				local D_hi = XOR(lanes_hi[26], SHL(lanes_hi[28], 1), SHR(lanes_lo[28], 31))
				lanes_lo[2], lanes_hi[2], lanes_lo[7], lanes_hi[7], lanes_lo[12], lanes_hi[12], lanes_lo[17], lanes_hi[17] = XOR(SHR(XOR(D_lo, lanes_lo[7]), 20), SHL(XOR(D_hi, lanes_hi[7]), 12)), XOR(SHR(XOR(D_hi, lanes_hi[7]), 20), SHL(XOR(D_lo, lanes_lo[7]), 12)), XOR(SHR(XOR(D_lo, lanes_lo[17]), 19), SHL(XOR(D_hi, lanes_hi[17]), 13)), XOR(SHR(XOR(D_hi, lanes_hi[17]), 19), SHL(XOR(D_lo, lanes_lo[17]), 13)), XOR(SHL(XOR(D_lo, lanes_lo[2]), 1), SHR(XOR(D_hi, lanes_hi[2]), 31)), XOR(SHL(XOR(D_hi, lanes_hi[2]), 1), SHR(XOR(D_lo, lanes_lo[2]), 31)), XOR(SHL(XOR(D_lo, lanes_lo[12]), 10), SHR(XOR(D_hi, lanes_hi[12]), 22)), XOR(SHL(XOR(D_hi, lanes_hi[12]), 10), SHR(XOR(D_lo, lanes_lo[12]), 22))
				local L, H = XOR(D_lo, lanes_lo[22]), XOR(D_hi, lanes_hi[22])
				lanes_lo[22], lanes_hi[22] = XOR(SHL(L, 2), SHR(H, 30)), XOR(SHL(H, 2), SHR(L, 30))
				D_lo = XOR(lanes_lo[27], SHL(lanes_lo[29], 1), SHR(lanes_hi[29], 31))
				D_hi = XOR(lanes_hi[27], SHL(lanes_hi[29], 1), SHR(lanes_lo[29], 31))
				lanes_lo[3], lanes_hi[3], lanes_lo[8], lanes_hi[8], lanes_lo[13], lanes_hi[13], lanes_lo[23], lanes_hi[23] = XOR(SHR(XOR(D_lo, lanes_lo[13]), 21), SHL(XOR(D_hi, lanes_hi[13]), 11)), XOR(SHR(XOR(D_hi, lanes_hi[13]), 21), SHL(XOR(D_lo, lanes_lo[13]), 11)), XOR(SHR(XOR(D_lo, lanes_lo[23]), 3), SHL(XOR(D_hi, lanes_hi[23]), 29)), XOR(SHR(XOR(D_hi, lanes_hi[23]), 3), SHL(XOR(D_lo, lanes_lo[23]), 29)), XOR(SHL(XOR(D_lo, lanes_lo[8]), 6), SHR(XOR(D_hi, lanes_hi[8]), 26)), XOR(SHL(XOR(D_hi, lanes_hi[8]), 6), SHR(XOR(D_lo, lanes_lo[8]), 26)), XOR(SHR(XOR(D_lo, lanes_lo[3]), 2), SHL(XOR(D_hi, lanes_hi[3]), 30)), XOR(SHR(XOR(D_hi, lanes_hi[3]), 2), SHL(XOR(D_lo, lanes_lo[3]), 30))
				L, H = XOR(D_lo, lanes_lo[18]), XOR(D_hi, lanes_hi[18])
				lanes_lo[18], lanes_hi[18] = XOR(SHL(L, 15), SHR(H, 17)), XOR(SHL(H, 15), SHR(L, 17))
				D_lo = XOR(lanes_lo[28], SHL(lanes_lo[30], 1), SHR(lanes_hi[30], 31))
				D_hi = XOR(lanes_hi[28], SHL(lanes_hi[30], 1), SHR(lanes_lo[30], 31))
				lanes_lo[4], lanes_hi[4], lanes_lo[9], lanes_hi[9], lanes_lo[19], lanes_hi[19], lanes_lo[24], lanes_hi[24] = XOR(SHL(XOR(D_lo, lanes_lo[19]), 21), SHR(XOR(D_hi, lanes_hi[19]), 11)), XOR(SHL(XOR(D_hi, lanes_hi[19]), 21), SHR(XOR(D_lo, lanes_lo[19]), 11)), XOR(SHL(XOR(D_lo, lanes_lo[4]), 28), SHR(XOR(D_hi, lanes_hi[4]), 4)), XOR(SHL(XOR(D_hi, lanes_hi[4]), 28), SHR(XOR(D_lo, lanes_lo[4]), 4)), XOR(SHR(XOR(D_lo, lanes_lo[24]), 8), SHL(XOR(D_hi, lanes_hi[24]), 24)), XOR(SHR(XOR(D_hi, lanes_hi[24]), 8), SHL(XOR(D_lo, lanes_lo[24]), 24)), XOR(SHR(XOR(D_lo, lanes_lo[9]), 9), SHL(XOR(D_hi, lanes_hi[9]), 23)), XOR(SHR(XOR(D_hi, lanes_hi[9]), 9), SHL(XOR(D_lo, lanes_lo[9]), 23))
				L, H = XOR(D_lo, lanes_lo[14]), XOR(D_hi, lanes_hi[14])
				lanes_lo[14], lanes_hi[14] = XOR(SHL(L, 25), SHR(H, 7)), XOR(SHL(H, 25), SHR(L, 7))
				D_lo = XOR(lanes_lo[29], SHL(lanes_lo[26], 1), SHR(lanes_hi[26], 31))
				D_hi = XOR(lanes_hi[29], SHL(lanes_hi[26], 1), SHR(lanes_lo[26], 31))
				lanes_lo[5], lanes_hi[5], lanes_lo[15], lanes_hi[15], lanes_lo[20], lanes_hi[20], lanes_lo[25], lanes_hi[25] = XOR(SHL(XOR(D_lo, lanes_lo[25]), 14), SHR(XOR(D_hi, lanes_hi[25]), 18)), XOR(SHL(XOR(D_hi, lanes_hi[25]), 14), SHR(XOR(D_lo, lanes_lo[25]), 18)), XOR(SHL(XOR(D_lo, lanes_lo[20]), 8), SHR(XOR(D_hi, lanes_hi[20]), 24)), XOR(SHL(XOR(D_hi, lanes_hi[20]), 8), SHR(XOR(D_lo, lanes_lo[20]), 24)), XOR(SHL(XOR(D_lo, lanes_lo[5]), 27), SHR(XOR(D_hi, lanes_hi[5]), 5)), XOR(SHL(XOR(D_hi, lanes_hi[5]), 27), SHR(XOR(D_lo, lanes_lo[5]), 5)), XOR(SHR(XOR(D_lo, lanes_lo[15]), 25), SHL(XOR(D_hi, lanes_hi[15]), 7)), XOR(SHR(XOR(D_hi, lanes_hi[15]), 25), SHL(XOR(D_lo, lanes_lo[15]), 7))
				L, H = XOR(D_lo, lanes_lo[10]), XOR(D_hi, lanes_hi[10])
				lanes_lo[10], lanes_hi[10] = XOR(SHL(L, 20), SHR(H, 12)), XOR(SHL(H, 20), SHR(L, 12))
				D_lo = XOR(lanes_lo[30], SHL(lanes_lo[27], 1), SHR(lanes_hi[27], 31))
				D_hi = XOR(lanes_hi[30], SHL(lanes_hi[27], 1), SHR(lanes_lo[27], 31))
				lanes_lo[6], lanes_hi[6], lanes_lo[11], lanes_hi[11], lanes_lo[16], lanes_hi[16], lanes_lo[21], lanes_hi[21] = XOR(SHL(XOR(D_lo, lanes_lo[11]), 3), SHR(XOR(D_hi, lanes_hi[11]), 29)), XOR(SHL(XOR(D_hi, lanes_hi[11]), 3), SHR(XOR(D_lo, lanes_lo[11]), 29)), XOR(SHL(XOR(D_lo, lanes_lo[21]), 18), SHR(XOR(D_hi, lanes_hi[21]), 14)), XOR(SHL(XOR(D_hi, lanes_hi[21]), 18), SHR(XOR(D_lo, lanes_lo[21]), 14)), XOR(SHR(XOR(D_lo, lanes_lo[6]), 28), SHL(XOR(D_hi, lanes_hi[6]), 4)), XOR(SHR(XOR(D_hi, lanes_hi[6]), 28), SHL(XOR(D_lo, lanes_lo[6]), 4)), XOR(SHR(XOR(D_lo, lanes_lo[16]), 23), SHL(XOR(D_hi, lanes_hi[16]), 9)), XOR(SHR(XOR(D_hi, lanes_hi[16]), 23), SHL(XOR(D_lo, lanes_lo[16]), 9))
				lanes_lo[1], lanes_hi[1] = XOR(D_lo, lanes_lo[1]), XOR(D_hi, lanes_hi[1])
				lanes_lo[1], lanes_lo[2], lanes_lo[3], lanes_lo[4], lanes_lo[5] = XOR(lanes_lo[1], AND(NOT(lanes_lo[2]), lanes_lo[3]), RC_lo[round_idx]), XOR(lanes_lo[2], AND(NOT(lanes_lo[3]), lanes_lo[4])), XOR(lanes_lo[3], AND(NOT(lanes_lo[4]), lanes_lo[5])), XOR(lanes_lo[4], AND(NOT(lanes_lo[5]), lanes_lo[1])), XOR(lanes_lo[5], AND(NOT(lanes_lo[1]), lanes_lo[2]))
				lanes_lo[6], lanes_lo[7], lanes_lo[8], lanes_lo[9], lanes_lo[10] = XOR(lanes_lo[9], AND(NOT(lanes_lo[10]), lanes_lo[6])), XOR(lanes_lo[10], AND(NOT(lanes_lo[6]), lanes_lo[7])), XOR(lanes_lo[6], AND(NOT(lanes_lo[7]), lanes_lo[8])), XOR(lanes_lo[7], AND(NOT(lanes_lo[8]), lanes_lo[9])), XOR(lanes_lo[8], AND(NOT(lanes_lo[9]), lanes_lo[10]))
				lanes_lo[11], lanes_lo[12], lanes_lo[13], lanes_lo[14], lanes_lo[15] = XOR(lanes_lo[12], AND(NOT(lanes_lo[13]), lanes_lo[14])), XOR(lanes_lo[13], AND(NOT(lanes_lo[14]), lanes_lo[15])), XOR(lanes_lo[14], AND(NOT(lanes_lo[15]), lanes_lo[11])), XOR(lanes_lo[15], AND(NOT(lanes_lo[11]), lanes_lo[12])), XOR(lanes_lo[11], AND(NOT(lanes_lo[12]), lanes_lo[13]))
				lanes_lo[16], lanes_lo[17], lanes_lo[18], lanes_lo[19], lanes_lo[20] = XOR(lanes_lo[20], AND(NOT(lanes_lo[16]), lanes_lo[17])), XOR(lanes_lo[16], AND(NOT(lanes_lo[17]), lanes_lo[18])), XOR(lanes_lo[17], AND(NOT(lanes_lo[18]), lanes_lo[19])), XOR(lanes_lo[18], AND(NOT(lanes_lo[19]), lanes_lo[20])), XOR(lanes_lo[19], AND(NOT(lanes_lo[20]), lanes_lo[16]))
				lanes_lo[21], lanes_lo[22], lanes_lo[23], lanes_lo[24], lanes_lo[25] = XOR(lanes_lo[23], AND(NOT(lanes_lo[24]), lanes_lo[25])), XOR(lanes_lo[24], AND(NOT(lanes_lo[25]), lanes_lo[21])), XOR(lanes_lo[25], AND(NOT(lanes_lo[21]), lanes_lo[22])), XOR(lanes_lo[21], AND(NOT(lanes_lo[22]), lanes_lo[23])), XOR(lanes_lo[22], AND(NOT(lanes_lo[23]), lanes_lo[24]))
				lanes_hi[1], lanes_hi[2], lanes_hi[3], lanes_hi[4], lanes_hi[5] = XOR(lanes_hi[1], AND(NOT(lanes_hi[2]), lanes_hi[3]), RC_hi[round_idx]), XOR(lanes_hi[2], AND(NOT(lanes_hi[3]), lanes_hi[4])), XOR(lanes_hi[3], AND(NOT(lanes_hi[4]), lanes_hi[5])), XOR(lanes_hi[4], AND(NOT(lanes_hi[5]), lanes_hi[1])), XOR(lanes_hi[5], AND(NOT(lanes_hi[1]), lanes_hi[2]))
				lanes_hi[6], lanes_hi[7], lanes_hi[8], lanes_hi[9], lanes_hi[10] = XOR(lanes_hi[9], AND(NOT(lanes_hi[10]), lanes_hi[6])), XOR(lanes_hi[10], AND(NOT(lanes_hi[6]), lanes_hi[7])), XOR(lanes_hi[6], AND(NOT(lanes_hi[7]), lanes_hi[8])), XOR(lanes_hi[7], AND(NOT(lanes_hi[8]), lanes_hi[9])), XOR(lanes_hi[8], AND(NOT(lanes_hi[9]), lanes_hi[10]))
				lanes_hi[11], lanes_hi[12], lanes_hi[13], lanes_hi[14], lanes_hi[15] = XOR(lanes_hi[12], AND(NOT(lanes_hi[13]), lanes_hi[14])), XOR(lanes_hi[13], AND(NOT(lanes_hi[14]), lanes_hi[15])), XOR(lanes_hi[14], AND(NOT(lanes_hi[15]), lanes_hi[11])), XOR(lanes_hi[15], AND(NOT(lanes_hi[11]), lanes_hi[12])), XOR(lanes_hi[11], AND(NOT(lanes_hi[12]), lanes_hi[13]))
				lanes_hi[16], lanes_hi[17], lanes_hi[18], lanes_hi[19], lanes_hi[20] = XOR(lanes_hi[20], AND(NOT(lanes_hi[16]), lanes_hi[17])), XOR(lanes_hi[16], AND(NOT(lanes_hi[17]), lanes_hi[18])), XOR(lanes_hi[17], AND(NOT(lanes_hi[18]), lanes_hi[19])), XOR(lanes_hi[18], AND(NOT(lanes_hi[19]), lanes_hi[20])), XOR(lanes_hi[19], AND(NOT(lanes_hi[20]), lanes_hi[16]))
				lanes_hi[21], lanes_hi[22], lanes_hi[23], lanes_hi[24], lanes_hi[25] = XOR(lanes_hi[23], AND(NOT(lanes_hi[24]), lanes_hi[25])), XOR(lanes_hi[24], AND(NOT(lanes_hi[25]), lanes_hi[21])), XOR(lanes_hi[25], AND(NOT(lanes_hi[21]), lanes_hi[22])), XOR(lanes_hi[21], AND(NOT(lanes_hi[22]), lanes_hi[23])), XOR(lanes_hi[22], AND(NOT(lanes_hi[23]), lanes_hi[24]))
			end
		end
	end

end


if branch == "LJ" then


	-- SHA256 implementation for "LuaJIT without FFI" branch

	function sha256_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W, K = common_W, sha2_K_hi
		for pos = offs, offs + size - 1, 64 do
			for j = 1, 16 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)
				W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d)
			end
			for j = 17, 64 do
				local a, b = W[j-15], W[j-2]
				W[j] = NORM( NORM( XOR(ROR(a, 7), ROL(a, 14), SHR(a, 3)) + XOR(ROL(b, 15), ROL(b, 13), SHR(b, 10)) ) + NORM( W[j-7] + W[j-16] ) )
			end
			local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
			for j = 1, 64, 8 do  -- Thanks to Peter Cawley for this workaround (unroll the loop to avoid "PHI shuffling too complex" due to PHIs overlap)
				local z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j] + W[j] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+1] + W[j+1] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+2] + W[j+2] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+3] + W[j+3] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+4] + W[j+4] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+5] + W[j+5] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+6] + W[j+6] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
				z = NORM( XOR(ROR(e, 6), ROR(e, 11), ROL(e, 7)) + XOR(g, AND(e, XOR(f, g))) + (K[j+7] + W[j+7] + h) )
				h, g, f, e = g, f, e, NORM(d + z)
				d, c, b, a = c, b, a, NORM( XOR(AND(a, XOR(b, c)), AND(b, c)) + XOR(ROR(a, 2), ROR(a, 13), ROL(a, 10)) + z )
			end
			H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4])
			H[5], H[6], H[7], H[8] = NORM(e + H[5]), NORM(f + H[6]), NORM(g + H[7]), NORM(h + H[8])
		end
	end

	local function ADD64_4(a_lo, a_hi, b_lo, b_hi, c_lo, c_hi, d_lo, d_hi)
		local sum_lo = a_lo % 2^32 + b_lo % 2^32 + c_lo % 2^32 + d_lo % 2^32
		local sum_hi = a_hi + b_hi + c_hi + d_hi
		local result_lo = NORM( sum_lo )
		local result_hi = NORM( sum_hi + floor(sum_lo / 2^32) )
		return result_lo, result_hi
	end

	if LuaJIT_arch == "x86" then  -- Special trick is required to avoid "PHI shuffling too complex" on x86 platform


		-- SHA512 implementation for "LuaJIT x86 without FFI" branch

		function sha512_feed_128(H_lo, H_hi, str, offs, size)
			-- offs >= 0, size >= 0, size is multiple of 128
			-- W1_hi, W1_lo, W2_hi, W2_lo, ...   Wk_hi = W[2*k-1], Wk_lo = W[2*k]
			local W, K_lo, K_hi = common_W, sha2_K_lo, sha2_K_hi
			for pos = offs, offs + size - 1, 128 do
				for j = 1, 16*2 do
					pos = pos + 4
					local a, b, c, d = byte(str, pos - 3, pos)
					W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d)
				end
				for jj = 17*2, 80*2, 2 do
					local a_lo, a_hi = W[jj-30], W[jj-31]
					local t_lo = XOR(OR(SHR(a_lo, 1), SHL(a_hi, 31)), OR(SHR(a_lo, 8), SHL(a_hi, 24)), OR(SHR(a_lo, 7), SHL(a_hi, 25)))
					local t_hi = XOR(OR(SHR(a_hi, 1), SHL(a_lo, 31)), OR(SHR(a_hi, 8), SHL(a_lo, 24)), SHR(a_hi, 7))
					local b_lo, b_hi = W[jj-4], W[jj-5]
					local u_lo = XOR(OR(SHR(b_lo, 19), SHL(b_hi, 13)), OR(SHL(b_lo, 3), SHR(b_hi, 29)), OR(SHR(b_lo, 6), SHL(b_hi, 26)))
					local u_hi = XOR(OR(SHR(b_hi, 19), SHL(b_lo, 13)), OR(SHL(b_hi, 3), SHR(b_lo, 29)), SHR(b_hi, 6))
					W[jj], W[jj-1] = ADD64_4(t_lo, t_hi, u_lo, u_hi, W[jj-14], W[jj-15], W[jj-32], W[jj-33])
				end
				local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
				local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
				local zero = 0
				for j = 1, 80 do
					local t_lo = XOR(g_lo, AND(e_lo, XOR(f_lo, g_lo)))
					local t_hi = XOR(g_hi, AND(e_hi, XOR(f_hi, g_hi)))
					local u_lo = XOR(OR(SHR(e_lo, 14), SHL(e_hi, 18)), OR(SHR(e_lo, 18), SHL(e_hi, 14)), OR(SHL(e_lo, 23), SHR(e_hi, 9)))
					local u_hi = XOR(OR(SHR(e_hi, 14), SHL(e_lo, 18)), OR(SHR(e_hi, 18), SHL(e_lo, 14)), OR(SHL(e_hi, 23), SHR(e_lo, 9)))
					local sum_lo = u_lo % 2^32 + t_lo % 2^32 + h_lo % 2^32 + K_lo[j] + W[2*j] % 2^32
					local z_lo, z_hi = NORM( sum_lo ), NORM( u_hi + t_hi + h_hi + K_hi[j] + W[2*j-1] + floor(sum_lo / 2^32) )
					zero = zero + zero  -- this thick is needed to avoid "PHI shuffling too complex" due to PHIs overlap
					h_lo, h_hi, g_lo, g_hi, f_lo, f_hi = OR(zero, g_lo), OR(zero, g_hi), OR(zero, f_lo), OR(zero, f_hi), OR(zero, e_lo), OR(zero, e_hi)
					local sum_lo = z_lo % 2^32 + d_lo % 2^32
					e_lo, e_hi = NORM( sum_lo ), NORM( z_hi + d_hi + floor(sum_lo / 2^32) )
					d_lo, d_hi, c_lo, c_hi, b_lo, b_hi = OR(zero, c_lo), OR(zero, c_hi), OR(zero, b_lo), OR(zero, b_hi), OR(zero, a_lo), OR(zero, a_hi)
					u_lo = XOR(OR(SHR(b_lo, 28), SHL(b_hi, 4)), OR(SHL(b_lo, 30), SHR(b_hi, 2)), OR(SHL(b_lo, 25), SHR(b_hi, 7)))
					u_hi = XOR(OR(SHR(b_hi, 28), SHL(b_lo, 4)), OR(SHL(b_hi, 30), SHR(b_lo, 2)), OR(SHL(b_hi, 25), SHR(b_lo, 7)))
					t_lo = OR(AND(d_lo, c_lo), AND(b_lo, XOR(d_lo, c_lo)))
					t_hi = OR(AND(d_hi, c_hi), AND(b_hi, XOR(d_hi, c_hi)))
					local sum_lo = z_lo % 2^32 + t_lo % 2^32 + u_lo % 2^32
					a_lo, a_hi = NORM( sum_lo ), NORM( z_hi + t_hi + u_hi + floor(sum_lo / 2^32) )
				end
				H_lo[1], H_hi[1] = ADD64_4(H_lo[1], H_hi[1], a_lo, a_hi, 0, 0, 0, 0)
				H_lo[2], H_hi[2] = ADD64_4(H_lo[2], H_hi[2], b_lo, b_hi, 0, 0, 0, 0)
				H_lo[3], H_hi[3] = ADD64_4(H_lo[3], H_hi[3], c_lo, c_hi, 0, 0, 0, 0)
				H_lo[4], H_hi[4] = ADD64_4(H_lo[4], H_hi[4], d_lo, d_hi, 0, 0, 0, 0)
				H_lo[5], H_hi[5] = ADD64_4(H_lo[5], H_hi[5], e_lo, e_hi, 0, 0, 0, 0)
				H_lo[6], H_hi[6] = ADD64_4(H_lo[6], H_hi[6], f_lo, f_hi, 0, 0, 0, 0)
				H_lo[7], H_hi[7] = ADD64_4(H_lo[7], H_hi[7], g_lo, g_hi, 0, 0, 0, 0)
				H_lo[8], H_hi[8] = ADD64_4(H_lo[8], H_hi[8], h_lo, h_hi, 0, 0, 0, 0)
			end
		end

	else  -- all platforms except x86


		-- SHA512 implementation for "LuaJIT non-x86 without FFI" branch

		function sha512_feed_128(H_lo, H_hi, str, offs, size)
			-- offs >= 0, size >= 0, size is multiple of 128
			-- W1_hi, W1_lo, W2_hi, W2_lo, ...   Wk_hi = W[2*k-1], Wk_lo = W[2*k]
			local W, K_lo, K_hi = common_W, sha2_K_lo, sha2_K_hi
			for pos = offs, offs + size - 1, 128 do
				for j = 1, 16*2 do
					pos = pos + 4
					local a, b, c, d = byte(str, pos - 3, pos)
					W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d)
				end
				for jj = 17*2, 80*2, 2 do
					local a_lo, a_hi = W[jj-30], W[jj-31]
					local t_lo = XOR(OR(SHR(a_lo, 1), SHL(a_hi, 31)), OR(SHR(a_lo, 8), SHL(a_hi, 24)), OR(SHR(a_lo, 7), SHL(a_hi, 25)))
					local t_hi = XOR(OR(SHR(a_hi, 1), SHL(a_lo, 31)), OR(SHR(a_hi, 8), SHL(a_lo, 24)), SHR(a_hi, 7))
					local b_lo, b_hi = W[jj-4], W[jj-5]
					local u_lo = XOR(OR(SHR(b_lo, 19), SHL(b_hi, 13)), OR(SHL(b_lo, 3), SHR(b_hi, 29)), OR(SHR(b_lo, 6), SHL(b_hi, 26)))
					local u_hi = XOR(OR(SHR(b_hi, 19), SHL(b_lo, 13)), OR(SHL(b_hi, 3), SHR(b_lo, 29)), SHR(b_hi, 6))
					W[jj], W[jj-1] = ADD64_4(t_lo, t_hi, u_lo, u_hi, W[jj-14], W[jj-15], W[jj-32], W[jj-33])
				end
				local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
				local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
				for j = 1, 80 do
					local t_lo = XOR(g_lo, AND(e_lo, XOR(f_lo, g_lo)))
					local t_hi = XOR(g_hi, AND(e_hi, XOR(f_hi, g_hi)))
					local u_lo = XOR(OR(SHR(e_lo, 14), SHL(e_hi, 18)), OR(SHR(e_lo, 18), SHL(e_hi, 14)), OR(SHL(e_lo, 23), SHR(e_hi, 9)))
					local u_hi = XOR(OR(SHR(e_hi, 14), SHL(e_lo, 18)), OR(SHR(e_hi, 18), SHL(e_lo, 14)), OR(SHL(e_hi, 23), SHR(e_lo, 9)))
					local sum_lo = u_lo % 2^32 + t_lo % 2^32 + h_lo % 2^32 + K_lo[j] + W[2*j] % 2^32
					local z_lo, z_hi = NORM( sum_lo ), NORM( u_hi + t_hi + h_hi + K_hi[j] + W[2*j-1] + floor(sum_lo / 2^32) )
					h_lo, h_hi, g_lo, g_hi, f_lo, f_hi = g_lo, g_hi, f_lo, f_hi, e_lo, e_hi
					local sum_lo = z_lo % 2^32 + d_lo % 2^32
					e_lo, e_hi = NORM( sum_lo ), NORM( z_hi + d_hi + floor(sum_lo / 2^32) )
					d_lo, d_hi, c_lo, c_hi, b_lo, b_hi = c_lo, c_hi, b_lo, b_hi, a_lo, a_hi
					u_lo = XOR(OR(SHR(b_lo, 28), SHL(b_hi, 4)), OR(SHL(b_lo, 30), SHR(b_hi, 2)), OR(SHL(b_lo, 25), SHR(b_hi, 7)))
					u_hi = XOR(OR(SHR(b_hi, 28), SHL(b_lo, 4)), OR(SHL(b_hi, 30), SHR(b_lo, 2)), OR(SHL(b_hi, 25), SHR(b_lo, 7)))
					t_lo = OR(AND(d_lo, c_lo), AND(b_lo, XOR(d_lo, c_lo)))
					t_hi = OR(AND(d_hi, c_hi), AND(b_hi, XOR(d_hi, c_hi)))
					local sum_lo = z_lo % 2^32 + u_lo % 2^32 + t_lo % 2^32
					a_lo, a_hi = NORM( sum_lo ), NORM( z_hi + u_hi + t_hi + floor(sum_lo / 2^32) )
				end
				H_lo[1], H_hi[1] = ADD64_4(H_lo[1], H_hi[1], a_lo, a_hi, 0, 0, 0, 0)
				H_lo[2], H_hi[2] = ADD64_4(H_lo[2], H_hi[2], b_lo, b_hi, 0, 0, 0, 0)
				H_lo[3], H_hi[3] = ADD64_4(H_lo[3], H_hi[3], c_lo, c_hi, 0, 0, 0, 0)
				H_lo[4], H_hi[4] = ADD64_4(H_lo[4], H_hi[4], d_lo, d_hi, 0, 0, 0, 0)
				H_lo[5], H_hi[5] = ADD64_4(H_lo[5], H_hi[5], e_lo, e_hi, 0, 0, 0, 0)
				H_lo[6], H_hi[6] = ADD64_4(H_lo[6], H_hi[6], f_lo, f_hi, 0, 0, 0, 0)
				H_lo[7], H_hi[7] = ADD64_4(H_lo[7], H_hi[7], g_lo, g_hi, 0, 0, 0, 0)
				H_lo[8], H_hi[8] = ADD64_4(H_lo[8], H_hi[8], h_lo, h_hi, 0, 0, 0, 0)
			end
		end

	end


	-- MD5 implementation for "LuaJIT without FFI" branch

	function md5_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W, K = common_W, md5_K
		for pos = offs, offs + size - 1, 64 do
			for j = 1, 16 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)
				W[j] = OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a)
			end
			local a, b, c, d = H[1], H[2], H[3], H[4]
			for j = 1, 16, 4 do
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j  ] + W[j  ] + a),  7) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+1] + W[j+1] + a), 12) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+2] + W[j+2] + a), 17) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(d, AND(b, XOR(c, d))) + (K[j+3] + W[j+3] + a), 22) + b)
			end
			for j = 17, 32, 4 do
				local g = 5*j-4
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j  ] + W[AND(g     , 15) + 1] + a),  5) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+1] + W[AND(g +  5, 15) + 1] + a),  9) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+2] + W[AND(g + 10, 15) + 1] + a), 14) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, AND(d, XOR(b, c))) + (K[j+3] + W[AND(g -  1, 15) + 1] + a), 20) + b)
			end
			for j = 33, 48, 4 do
				local g = 3*j+2
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j  ] + W[AND(g    , 15) + 1] + a),  4) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+1] + W[AND(g + 3, 15) + 1] + a), 11) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+2] + W[AND(g + 6, 15) + 1] + a), 16) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(b, c, d) + (K[j+3] + W[AND(g - 7, 15) + 1] + a), 23) + b)
			end
			for j = 49, 64, 4 do
				local g = j*7
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j  ] + W[AND(g - 7, 15) + 1] + a),  6) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+1] + W[AND(g    , 15) + 1] + a), 10) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+2] + W[AND(g + 7, 15) + 1] + a), 15) + b)
				a, d, c, b = d, c, b, NORM(ROL(XOR(c, OR(b, NOT(d))) + (K[j+3] + W[AND(g - 2, 15) + 1] + a), 21) + b)
			end
			H[1], H[2], H[3], H[4] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4])
		end
	end


	-- SHA-1 implementation for "LuaJIT without FFI" branch

	function sha1_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W = common_W
		for pos = offs, offs + size - 1, 64 do
			for j = 1, 16 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)
				W[j] = OR(SHL(a, 24), SHL(b, 16), SHL(c, 8), d)
			end
			for j = 17, 80 do
				W[j] = ROL(XOR(W[j-3], W[j-8], W[j-14], W[j-16]), 1)
			end
			local a, b, c, d, e = H[1], H[2], H[3], H[4], H[5]
			for j = 1, 20, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j]   + 0x5A827999 + e))          -- constant = floor(2^30 * sqrt(2))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+1] + 0x5A827999 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+2] + 0x5A827999 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+3] + 0x5A827999 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(d, AND(b, XOR(d, c))) + (W[j+4] + 0x5A827999 + e))
			end
			for j = 21, 40, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j]   + 0x6ED9EBA1 + e))                       -- 2^30 * sqrt(3)
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0x6ED9EBA1 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0x6ED9EBA1 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0x6ED9EBA1 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0x6ED9EBA1 + e))
			end
			for j = 41, 60, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j]   + 0x8F1BBCDC + e))  -- 2^30 * sqrt(5)
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+1] + 0x8F1BBCDC + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+2] + 0x8F1BBCDC + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+3] + 0x8F1BBCDC + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(AND(d, XOR(b, c)), AND(b, c)) + (W[j+4] + 0x8F1BBCDC + e))
			end
			for j = 61, 80, 5 do
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j]   + 0xCA62C1D6 + e))                       -- 2^30 * sqrt(10)
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+1] + 0xCA62C1D6 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+2] + 0xCA62C1D6 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+3] + 0xCA62C1D6 + e))
				e, d, c, b, a = d, c, ROR(b, 2), a, NORM(ROL(a, 5) + XOR(b, c, d) + (W[j+4] + 0xCA62C1D6 + e))
			end
			H[1], H[2], H[3], H[4], H[5] = NORM(a + H[1]), NORM(b + H[2]), NORM(c + H[3]), NORM(d + H[4]), NORM(e + H[5])
		end
	end


	-- BLAKE2b implementation for "LuaJIT without FFI" branch

	do
		local v_lo, v_hi = {}, {}

		local function G(a, b, c, d, k1, k2)
			local W = common_W
			local va_lo, vb_lo, vc_lo, vd_lo = v_lo[a], v_lo[b], v_lo[c], v_lo[d]
			local va_hi, vb_hi, vc_hi, vd_hi = v_hi[a], v_hi[b], v_hi[c], v_hi[d]
			local z = W[2*k1-1] + (va_lo % 2^32 + vb_lo % 2^32)
			va_lo = NORM(z)
			va_hi = NORM(W[2*k1] + (va_hi + vb_hi + floor(z / 2^32)))
			vd_lo, vd_hi = XOR(vd_hi, va_hi), XOR(vd_lo, va_lo)
			z = vc_lo % 2^32 + vd_lo % 2^32
			vc_lo = NORM(z)
			vc_hi = NORM(vc_hi + vd_hi + floor(z / 2^32))
			vb_lo, vb_hi = XOR(vb_lo, vc_lo), XOR(vb_hi, vc_hi)
			vb_lo, vb_hi = XOR(SHR(vb_lo, 24), SHL(vb_hi, 8)), XOR(SHR(vb_hi, 24), SHL(vb_lo, 8))
			z = W[2*k2-1] + (va_lo % 2^32 + vb_lo % 2^32)
			va_lo = NORM(z)
			va_hi = NORM(W[2*k2] + (va_hi + vb_hi + floor(z / 2^32)))
			vd_lo, vd_hi = XOR(vd_lo, va_lo), XOR(vd_hi, va_hi)
			vd_lo, vd_hi = XOR(SHR(vd_lo, 16), SHL(vd_hi, 16)), XOR(SHR(vd_hi, 16), SHL(vd_lo, 16))
			z = vc_lo % 2^32 + vd_lo % 2^32
			vc_lo = NORM(z)
			vc_hi = NORM(vc_hi + vd_hi + floor(z / 2^32))
			vb_lo, vb_hi = XOR(vb_lo, vc_lo), XOR(vb_hi, vc_hi)
			vb_lo, vb_hi = XOR(SHL(vb_lo, 1), SHR(vb_hi, 31)), XOR(SHL(vb_hi, 1), SHR(vb_lo, 31))
			v_lo[a], v_lo[b], v_lo[c], v_lo[d] = va_lo, vb_lo, vc_lo, vd_lo
			v_hi[a], v_hi[b], v_hi[c], v_hi[d] = va_hi, vb_hi, vc_hi, vd_hi
		end

		function blake2b_feed_128(H_lo, H_hi, str, offs, size, bytes_compressed, last_block_size, is_last_node)
			-- offs >= 0, size >= 0, size is multiple of 128
			local W = common_W
			local h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
			local h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
			for pos = offs, offs + size - 1, 128 do
				if str then
					for j = 1, 32 do
						pos = pos + 4
						local a, b, c, d = byte(str, pos - 3, pos)
						W[j] = d * 2^24 + OR(SHL(c, 16), SHL(b, 8), a)
					end
				end
				v_lo[0x0], v_lo[0x1], v_lo[0x2], v_lo[0x3], v_lo[0x4], v_lo[0x5], v_lo[0x6], v_lo[0x7] = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
				v_lo[0x8], v_lo[0x9], v_lo[0xA], v_lo[0xB], v_lo[0xC], v_lo[0xD], v_lo[0xE], v_lo[0xF] = sha2_H_lo[1], sha2_H_lo[2], sha2_H_lo[3], sha2_H_lo[4], sha2_H_lo[5], sha2_H_lo[6], sha2_H_lo[7], sha2_H_lo[8]
				v_hi[0x0], v_hi[0x1], v_hi[0x2], v_hi[0x3], v_hi[0x4], v_hi[0x5], v_hi[0x6], v_hi[0x7] = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
				v_hi[0x8], v_hi[0x9], v_hi[0xA], v_hi[0xB], v_hi[0xC], v_hi[0xD], v_hi[0xE], v_hi[0xF] = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4], sha2_H_hi[5], sha2_H_hi[6], sha2_H_hi[7], sha2_H_hi[8]
				bytes_compressed = bytes_compressed + (last_block_size or 128)
				local t0_lo = bytes_compressed % 2^32
				local t0_hi = floor(bytes_compressed / 2^32)
				v_lo[0xC] = XOR(v_lo[0xC], t0_lo)  -- t0 = low_8_bytes(bytes_compressed)
				v_hi[0xC] = XOR(v_hi[0xC], t0_hi)
				-- t1 = high_8_bytes(bytes_compressed) = 0,  message length is always below 2^53 bytes
				if last_block_size then  -- flag f0
					v_lo[0xE] = NOT(v_lo[0xE])
					v_hi[0xE] = NOT(v_hi[0xE])
				end
				if is_last_node then  -- flag f1
					v_lo[0xF] = NOT(v_lo[0xF])
					v_hi[0xF] = NOT(v_hi[0xF])
				end
				for j = 1, 12 do
					local row = sigma[j]
					G(0, 4,  8, 12, row[ 1], row[ 2])
					G(1, 5,  9, 13, row[ 3], row[ 4])
					G(2, 6, 10, 14, row[ 5], row[ 6])
					G(3, 7, 11, 15, row[ 7], row[ 8])
					G(0, 5, 10, 15, row[ 9], row[10])
					G(1, 6, 11, 12, row[11], row[12])
					G(2, 7,  8, 13, row[13], row[14])
					G(3, 4,  9, 14, row[15], row[16])
				end
				h1_lo = XOR(h1_lo, v_lo[0x0], v_lo[0x8])
				h2_lo = XOR(h2_lo, v_lo[0x1], v_lo[0x9])
				h3_lo = XOR(h3_lo, v_lo[0x2], v_lo[0xA])
				h4_lo = XOR(h4_lo, v_lo[0x3], v_lo[0xB])
				h5_lo = XOR(h5_lo, v_lo[0x4], v_lo[0xC])
				h6_lo = XOR(h6_lo, v_lo[0x5], v_lo[0xD])
				h7_lo = XOR(h7_lo, v_lo[0x6], v_lo[0xE])
				h8_lo = XOR(h8_lo, v_lo[0x7], v_lo[0xF])
				h1_hi = XOR(h1_hi, v_hi[0x0], v_hi[0x8])
				h2_hi = XOR(h2_hi, v_hi[0x1], v_hi[0x9])
				h3_hi = XOR(h3_hi, v_hi[0x2], v_hi[0xA])
				h4_hi = XOR(h4_hi, v_hi[0x3], v_hi[0xB])
				h5_hi = XOR(h5_hi, v_hi[0x4], v_hi[0xC])
				h6_hi = XOR(h6_hi, v_hi[0x5], v_hi[0xD])
				h7_hi = XOR(h7_hi, v_hi[0x6], v_hi[0xE])
				h8_hi = XOR(h8_hi, v_hi[0x7], v_hi[0xF])
			end
			H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] = h1_lo % 2^32, h2_lo % 2^32, h3_lo % 2^32, h4_lo % 2^32, h5_lo % 2^32, h6_lo % 2^32, h7_lo % 2^32, h8_lo % 2^32
			H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] = h1_hi % 2^32, h2_hi % 2^32, h3_hi % 2^32, h4_hi % 2^32, h5_hi % 2^32, h6_hi % 2^32, h7_hi % 2^32, h8_hi % 2^32
			return bytes_compressed
		end

	end
end


if branch == "FFI" or branch == "LJ" then


	-- BLAKE2s and BLAKE3 implementations for "LuaJIT with FFI" and "LuaJIT without FFI" branches

	do
		local W = common_W_blake2s
		local v = v_for_blake2s_feed_64

		local function G(a, b, c, d, k1, k2)
			local va, vb, vc, vd = v[a], v[b], v[c], v[d]
			va = NORM(W[k1] + (va + vb))
			vd = ROR(XOR(vd, va), 16)
			vc = NORM(vc + vd)
			vb = ROR(XOR(vb, vc), 12)
			va = NORM(W[k2] + (va + vb))
			vd = ROR(XOR(vd, va), 8)
			vc = NORM(vc + vd)
			vb = ROR(XOR(vb, vc), 7)
			v[a], v[b], v[c], v[d] = va, vb, vc, vd
		end

		function blake2s_feed_64(H, str, offs, size, bytes_compressed, last_block_size, is_last_node)
			-- offs >= 0, size >= 0, size is multiple of 64
			local h1, h2, h3, h4, h5, h6, h7, h8 = NORM(H[1]), NORM(H[2]), NORM(H[3]), NORM(H[4]), NORM(H[5]), NORM(H[6]), NORM(H[7]), NORM(H[8])
			for pos = offs, offs + size - 1, 64 do
				if str then
					for j = 1, 16 do
						pos = pos + 4
						local a, b, c, d = byte(str, pos - 3, pos)
						W[j] = OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a)
					end
				end
				v[0x0], v[0x1], v[0x2], v[0x3], v[0x4], v[0x5], v[0x6], v[0x7] = h1, h2, h3, h4, h5, h6, h7, h8
				v[0x8], v[0x9], v[0xA], v[0xB], v[0xE], v[0xF] = NORM(sha2_H_hi[1]), NORM(sha2_H_hi[2]), NORM(sha2_H_hi[3]), NORM(sha2_H_hi[4]), NORM(sha2_H_hi[7]), NORM(sha2_H_hi[8])
				bytes_compressed = bytes_compressed + (last_block_size or 64)
				local t0 = bytes_compressed % 2^32
				local t1 = floor(bytes_compressed / 2^32)
				v[0xC] = XOR(sha2_H_hi[5], t0)  -- t0 = low_4_bytes(bytes_compressed)
				v[0xD] = XOR(sha2_H_hi[6], t1)  -- t1 = high_4_bytes(bytes_compressed
				if last_block_size then  -- flag f0
					v[0xE] = NOT(v[0xE])
				end
				if is_last_node then  -- flag f1
					v[0xF] = NOT(v[0xF])
				end
				for j = 1, 10 do
					local row = sigma[j]
					G(0, 4,  8, 12, row[ 1], row[ 2])
					G(1, 5,  9, 13, row[ 3], row[ 4])
					G(2, 6, 10, 14, row[ 5], row[ 6])
					G(3, 7, 11, 15, row[ 7], row[ 8])
					G(0, 5, 10, 15, row[ 9], row[10])
					G(1, 6, 11, 12, row[11], row[12])
					G(2, 7,  8, 13, row[13], row[14])
					G(3, 4,  9, 14, row[15], row[16])
				end
				h1 = XOR(h1, v[0x0], v[0x8])
				h2 = XOR(h2, v[0x1], v[0x9])
				h3 = XOR(h3, v[0x2], v[0xA])
				h4 = XOR(h4, v[0x3], v[0xB])
				h5 = XOR(h5, v[0x4], v[0xC])
				h6 = XOR(h6, v[0x5], v[0xD])
				h7 = XOR(h7, v[0x6], v[0xE])
				h8 = XOR(h8, v[0x7], v[0xF])
			end
			H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
			return bytes_compressed
		end

		function blake3_feed_64(str, offs, size, flags, chunk_index, H_in, H_out, wide_output, block_length)
			-- offs >= 0, size >= 0, size is multiple of 64
			block_length = block_length or 64
			local h1, h2, h3, h4, h5, h6, h7, h8 = NORM(H_in[1]), NORM(H_in[2]), NORM(H_in[3]), NORM(H_in[4]), NORM(H_in[5]), NORM(H_in[6]), NORM(H_in[7]), NORM(H_in[8])
			H_out = H_out or H_in
			for pos = offs, offs + size - 1, 64 do
				if str then
					for j = 1, 16 do
						pos = pos + 4
						local a, b, c, d = byte(str, pos - 3, pos)
						W[j] = OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a)
					end
				end
				v[0x0], v[0x1], v[0x2], v[0x3], v[0x4], v[0x5], v[0x6], v[0x7] = h1, h2, h3, h4, h5, h6, h7, h8
				v[0x8], v[0x9], v[0xA], v[0xB] = NORM(sha2_H_hi[1]), NORM(sha2_H_hi[2]), NORM(sha2_H_hi[3]), NORM(sha2_H_hi[4])
				v[0xC] = NORM(chunk_index % 2^32)   -- t0 = low_4_bytes(chunk_index)
				v[0xD] = floor(chunk_index / 2^32)  -- t1 = high_4_bytes(chunk_index)
				v[0xE], v[0xF] = block_length, flags
				for j = 1, 7 do
					G(0, 4,  8, 12, perm_blake3[j],      perm_blake3[j + 14])
					G(1, 5,  9, 13, perm_blake3[j + 1],  perm_blake3[j + 2])
					G(2, 6, 10, 14, perm_blake3[j + 16], perm_blake3[j + 7])
					G(3, 7, 11, 15, perm_blake3[j + 15], perm_blake3[j + 17])
					G(0, 5, 10, 15, perm_blake3[j + 21], perm_blake3[j + 5])
					G(1, 6, 11, 12, perm_blake3[j + 3],  perm_blake3[j + 6])
					G(2, 7,  8, 13, perm_blake3[j + 4],  perm_blake3[j + 18])
					G(3, 4,  9, 14, perm_blake3[j + 19], perm_blake3[j + 20])
				end
				if wide_output then
					H_out[ 9] = XOR(h1, v[0x8])
					H_out[10] = XOR(h2, v[0x9])
					H_out[11] = XOR(h3, v[0xA])
					H_out[12] = XOR(h4, v[0xB])
					H_out[13] = XOR(h5, v[0xC])
					H_out[14] = XOR(h6, v[0xD])
					H_out[15] = XOR(h7, v[0xE])
					H_out[16] = XOR(h8, v[0xF])
				end
				h1 = XOR(v[0x0], v[0x8])
				h2 = XOR(v[0x1], v[0x9])
				h3 = XOR(v[0x2], v[0xA])
				h4 = XOR(v[0x3], v[0xB])
				h5 = XOR(v[0x4], v[0xC])
				h6 = XOR(v[0x5], v[0xD])
				h7 = XOR(v[0x6], v[0xE])
				h8 = XOR(v[0x7], v[0xF])
			end
			H_out[1], H_out[2], H_out[3], H_out[4], H_out[5], H_out[6], H_out[7], H_out[8] = h1, h2, h3, h4, h5, h6, h7, h8
		end

	end

end


if branch == "INT64" then


	-- implementation for Lua 5.3/5.4

	hi_factor = 4294967296
	hi_factor_keccak = 4294967296
	lanes_index_base = 1

	HEX64, XORA5, XOR_BYTE, sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed, blake2s_feed_64, blake2b_feed_128, blake3_feed_64 = load[=[-- branch "INT64"
      local md5_next_shift, md5_K, sha2_K_lo, sha2_K_hi, build_keccak_format, sha3_RC_lo, sigma, common_W, sha2_H_lo, sha2_H_hi, perm_blake3 = ...
      local string_format, string_unpack = string.format, string.unpack

      local function HEX64(x)
         return string_format("%016x", x)
      end

      local function XORA5(x, y)
         return x ~ (y or 0xa5a5a5a5a5a5a5a5)
      end

      local function XOR_BYTE(x, y)
         return x ~ y
      end

      local function sha256_feed_64(H, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W, K = common_W, sha2_K_hi
         local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
         for pos = offs + 1, offs + size, 64 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
               string_unpack(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4", str, pos)
            for j = 17, 64 do
               local a = W[j-15]
               a = a<<32 | a
               local b = W[j-2]
               b = b<<32 | b
               W[j] = (a>>7 ~ a>>18 ~ a>>35) + (b>>17 ~ b>>19 ~ b>>42) + W[j-7] + W[j-16] & (1<<32)-1
            end
            local a, b, c, d, e, f, g, h = h1, h2, h3, h4, h5, h6, h7, h8
            for j = 1, 64 do
               e = e<<32 | e & (1<<32)-1
               local z = (e>>6 ~ e>>11 ~ e>>25) + (g ~ e & (f ~ g)) + h + K[j] + W[j]
               h = g
               g = f
               f = e
               e = z + d
               d = c
               c = b
               b = a
               a = a<<32 | a & (1<<32)-1
               a = z + ((a ~ c) & d ~ a & c) + (a>>2 ~ a>>13 ~ a>>22)
            end
            h1 = a + h1
            h2 = b + h2
            h3 = c + h3
            h4 = d + h4
            h5 = e + h5
            h6 = f + h6
            h7 = g + h7
            h8 = h + h8
         end
         H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
      end

      local function sha512_feed_128(H, _, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 128
         local W, K = common_W, sha2_K_lo
         local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
         for pos = offs + 1, offs + size, 128 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
               string_unpack(">i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8", str, pos)
            for j = 17, 80 do
               local a = W[j-15]
               local b = W[j-2]
               W[j] = (a >> 1 ~ a >> 7 ~ a >> 8 ~ a << 56 ~ a << 63) + (b >> 6 ~ b >> 19 ~ b >> 61 ~ b << 3 ~ b << 45) + W[j-7] + W[j-16]
            end
            local a, b, c, d, e, f, g, h = h1, h2, h3, h4, h5, h6, h7, h8
            for j = 1, 80 do
               local z = (e >> 14 ~ e >> 18 ~ e >> 41 ~ e << 23 ~ e << 46 ~ e << 50) + (g ~ e & (f ~ g)) + h + K[j] + W[j]
               h = g
               g = f
               f = e
               e = z + d
               d = c
               c = b
               b = a
               a = z + ((a ~ c) & d ~ a & c) + (a >> 28 ~ a >> 34 ~ a >> 39 ~ a << 25 ~ a << 30 ~ a << 36)
            end
            h1 = a + h1
            h2 = b + h2
            h3 = c + h3
            h4 = d + h4
            h5 = e + h5
            h6 = f + h6
            h7 = g + h7
            h8 = h + h8
         end
         H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
      end

      local function md5_feed_64(H, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W, K, md5_next_shift = common_W, md5_K, md5_next_shift
         local h1, h2, h3, h4 = H[1], H[2], H[3], H[4]
         for pos = offs + 1, offs + size, 64 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
               string_unpack("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4", str, pos)
            local a, b, c, d = h1, h2, h3, h4
            local s = 32-7
            for j = 1, 16 do
               local F = (d ~ b & (c ~ d)) + a + K[j] + W[j]
               a = d
               d = c
               c = b
               b = ((F<<32 | F & (1<<32)-1) >> s) + b
               s = md5_next_shift[s]
            end
            s = 32-5
            for j = 17, 32 do
               local F = (c ~ d & (b ~ c)) + a + K[j] + W[(5*j-4 & 15) + 1]
               a = d
               d = c
               c = b
               b = ((F<<32 | F & (1<<32)-1) >> s) + b
               s = md5_next_shift[s]
            end
            s = 32-4
            for j = 33, 48 do
               local F = (b ~ c ~ d) + a + K[j] + W[(3*j+2 & 15) + 1]
               a = d
               d = c
               c = b
               b = ((F<<32 | F & (1<<32)-1) >> s) + b
               s = md5_next_shift[s]
            end
            s = 32-6
            for j = 49, 64 do
               local F = (c ~ (b | ~d)) + a + K[j] + W[(j*7-7 & 15) + 1]
               a = d
               d = c
               c = b
               b = ((F<<32 | F & (1<<32)-1) >> s) + b
               s = md5_next_shift[s]
            end
            h1 = a + h1
            h2 = b + h2
            h3 = c + h3
            h4 = d + h4
         end
         H[1], H[2], H[3], H[4] = h1, h2, h3, h4
      end

      local function sha1_feed_64(H, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W = common_W
         local h1, h2, h3, h4, h5 = H[1], H[2], H[3], H[4], H[5]
         for pos = offs + 1, offs + size, 64 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
               string_unpack(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4", str, pos)
            for j = 17, 80 do
               local a = W[j-3] ~ W[j-8] ~ W[j-14] ~ W[j-16]
               W[j] = (a<<32 | a) << 1 >> 32
            end
            local a, b, c, d, e = h1, h2, h3, h4, h5
            for j = 1, 20 do
               local z = ((a<<32 | a & (1<<32)-1) >> 27) + (d ~ b & (c ~ d)) + 0x5A827999 + W[j] + e      -- constant = floor(2^30 * sqrt(2))
               e = d
               d = c
               c = (b<<32 | b & (1<<32)-1) >> 2
               b = a
               a = z
            end
            for j = 21, 40 do
               local z = ((a<<32 | a & (1<<32)-1) >> 27) + (b ~ c ~ d) + 0x6ED9EBA1 + W[j] + e            -- 2^30 * sqrt(3)
               e = d
               d = c
               c = (b<<32 | b & (1<<32)-1) >> 2
               b = a
               a = z
            end
            for j = 41, 60 do
               local z = ((a<<32 | a & (1<<32)-1) >> 27) + ((b ~ c) & d ~ b & c) + 0x8F1BBCDC + W[j] + e  -- 2^30 * sqrt(5)
               e = d
               d = c
               c = (b<<32 | b & (1<<32)-1) >> 2
               b = a
               a = z
            end
            for j = 61, 80 do
               local z = ((a<<32 | a & (1<<32)-1) >> 27) + (b ~ c ~ d) + 0xCA62C1D6 + W[j] + e            -- 2^30 * sqrt(10)
               e = d
               d = c
               c = (b<<32 | b & (1<<32)-1) >> 2
               b = a
               a = z
            end
            h1 = a + h1
            h2 = b + h2
            h3 = c + h3
            h4 = d + h4
            h5 = e + h5
         end
         H[1], H[2], H[3], H[4], H[5] = h1, h2, h3, h4, h5
      end

      local keccak_format_i8 = build_keccak_format("i8")

      local function keccak_feed(lanes, _, str, offs, size, block_size_in_bytes)
         -- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8
         local RC = sha3_RC_lo
         local qwords_qty = block_size_in_bytes / 8
         local keccak_format = keccak_format_i8[qwords_qty]
         for pos = offs + 1, offs + size, block_size_in_bytes do
            local qwords_from_message = {string_unpack(keccak_format, str, pos)}
            for j = 1, qwords_qty do
               lanes[j] = lanes[j] ~ qwords_from_message[j]
            end
            local L01, L02, L03, L04, L05, L06, L07, L08, L09, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19, L20, L21, L22, L23, L24, L25 =
               lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7], lanes[8], lanes[9], lanes[10], lanes[11], lanes[12], lanes[13],
               lanes[14], lanes[15], lanes[16], lanes[17], lanes[18], lanes[19], lanes[20], lanes[21], lanes[22], lanes[23], lanes[24], lanes[25]
            for round_idx = 1, 24 do
               local C1 = L01 ~ L06 ~ L11 ~ L16 ~ L21
               local C2 = L02 ~ L07 ~ L12 ~ L17 ~ L22
               local C3 = L03 ~ L08 ~ L13 ~ L18 ~ L23
               local C4 = L04 ~ L09 ~ L14 ~ L19 ~ L24
               local C5 = L05 ~ L10 ~ L15 ~ L20 ~ L25
               local D = C1 ~ C3<<1 ~ C3>>63
               local T0 = D ~ L02
               local T1 = D ~ L07
               local T2 = D ~ L12
               local T3 = D ~ L17
               local T4 = D ~ L22
               L02 = T1<<44 ~ T1>>20
               L07 = T3<<45 ~ T3>>19
               L12 = T0<<1 ~ T0>>63
               L17 = T2<<10 ~ T2>>54
               L22 = T4<<2 ~ T4>>62
               D = C2 ~ C4<<1 ~ C4>>63
               T0 = D ~ L03
               T1 = D ~ L08
               T2 = D ~ L13
               T3 = D ~ L18
               T4 = D ~ L23
               L03 = T2<<43 ~ T2>>21
               L08 = T4<<61 ~ T4>>3
               L13 = T1<<6 ~ T1>>58
               L18 = T3<<15 ~ T3>>49
               L23 = T0<<62 ~ T0>>2
               D = C3 ~ C5<<1 ~ C5>>63
               T0 = D ~ L04
               T1 = D ~ L09
               T2 = D ~ L14
               T3 = D ~ L19
               T4 = D ~ L24
               L04 = T3<<21 ~ T3>>43
               L09 = T0<<28 ~ T0>>36
               L14 = T2<<25 ~ T2>>39
               L19 = T4<<56 ~ T4>>8
               L24 = T1<<55 ~ T1>>9
               D = C4 ~ C1<<1 ~ C1>>63
               T0 = D ~ L05
               T1 = D ~ L10
               T2 = D ~ L15
               T3 = D ~ L20
               T4 = D ~ L25
               L05 = T4<<14 ~ T4>>50
               L10 = T1<<20 ~ T1>>44
               L15 = T3<<8 ~ T3>>56
               L20 = T0<<27 ~ T0>>37
               L25 = T2<<39 ~ T2>>25
               D = C5 ~ C2<<1 ~ C2>>63
               T1 = D ~ L06
               T2 = D ~ L11
               T3 = D ~ L16
               T4 = D ~ L21
               L06 = T2<<3 ~ T2>>61
               L11 = T4<<18 ~ T4>>46
               L16 = T1<<36 ~ T1>>28
               L21 = T3<<41 ~ T3>>23
               L01 = D ~ L01
               L01, L02, L03, L04, L05 = L01 ~ ~L02 & L03, L02 ~ ~L03 & L04, L03 ~ ~L04 & L05, L04 ~ ~L05 & L01, L05 ~ ~L01 & L02
               L06, L07, L08, L09, L10 = L09 ~ ~L10 & L06, L10 ~ ~L06 & L07, L06 ~ ~L07 & L08, L07 ~ ~L08 & L09, L08 ~ ~L09 & L10
               L11, L12, L13, L14, L15 = L12 ~ ~L13 & L14, L13 ~ ~L14 & L15, L14 ~ ~L15 & L11, L15 ~ ~L11 & L12, L11 ~ ~L12 & L13
               L16, L17, L18, L19, L20 = L20 ~ ~L16 & L17, L16 ~ ~L17 & L18, L17 ~ ~L18 & L19, L18 ~ ~L19 & L20, L19 ~ ~L20 & L16
               L21, L22, L23, L24, L25 = L23 ~ ~L24 & L25, L24 ~ ~L25 & L21, L25 ~ ~L21 & L22, L21 ~ ~L22 & L23, L22 ~ ~L23 & L24
               L01 = L01 ~ RC[round_idx]
            end
            lanes[1]  = L01
            lanes[2]  = L02
            lanes[3]  = L03
            lanes[4]  = L04
            lanes[5]  = L05
            lanes[6]  = L06
            lanes[7]  = L07
            lanes[8]  = L08
            lanes[9]  = L09
            lanes[10] = L10
            lanes[11] = L11
            lanes[12] = L12
            lanes[13] = L13
            lanes[14] = L14
            lanes[15] = L15
            lanes[16] = L16
            lanes[17] = L17
            lanes[18] = L18
            lanes[19] = L19
            lanes[20] = L20
            lanes[21] = L21
            lanes[22] = L22
            lanes[23] = L23
            lanes[24] = L24
            lanes[25] = L25
         end
      end

      local function blake2s_feed_64(H, str, offs, size, bytes_compressed, last_block_size, is_last_node)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W = common_W
         local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
         for pos = offs + 1, offs + size, 64 do
            if str then
               W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
                  string_unpack("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4", str, pos)
            end
            local v0, v1, v2, v3, v4, v5, v6, v7 = h1, h2, h3, h4, h5, h6, h7, h8
            local v8, v9, vA, vB, vC, vD, vE, vF = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4], sha2_H_hi[5], sha2_H_hi[6], sha2_H_hi[7], sha2_H_hi[8]
            bytes_compressed = bytes_compressed + (last_block_size or 64)
            vC = vC ~ bytes_compressed        -- t0 = low_4_bytes(bytes_compressed)
            vD = vD ~ bytes_compressed >> 32  -- t1 = high_4_bytes(bytes_compressed)
            if last_block_size then  -- flag f0
               vE = ~vE
            end
            if is_last_node then  -- flag f1
               vF = ~vF
            end
            for j = 1, 10 do
               local row = sigma[j]
               v0 = v0 + v4 + W[row[1]]
               vC = vC ~ v0
               vC = (vC & (1<<32)-1) >> 16 | vC << 16
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = (v4 & (1<<32)-1) >> 12 | v4 << 20
               v0 = v0 + v4 + W[row[2]]
               vC = vC ~ v0
               vC = (vC & (1<<32)-1) >> 8 | vC << 24
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = (v4 & (1<<32)-1) >> 7 | v4 << 25
               v1 = v1 + v5 + W[row[3]]
               vD = vD ~ v1
               vD = (vD & (1<<32)-1) >> 16 | vD << 16
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = (v5 & (1<<32)-1) >> 12 | v5 << 20
               v1 = v1 + v5 + W[row[4]]
               vD = vD ~ v1
               vD = (vD & (1<<32)-1) >> 8 | vD << 24
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = (v5 & (1<<32)-1) >> 7 | v5 << 25
               v2 = v2 + v6 + W[row[5]]
               vE = vE ~ v2
               vE = (vE & (1<<32)-1) >> 16 | vE << 16
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = (v6 & (1<<32)-1) >> 12 | v6 << 20
               v2 = v2 + v6 + W[row[6]]
               vE = vE ~ v2
               vE = (vE & (1<<32)-1) >> 8 | vE << 24
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = (v6 & (1<<32)-1) >> 7 | v6 << 25
               v3 = v3 + v7 + W[row[7]]
               vF = vF ~ v3
               vF = (vF & (1<<32)-1) >> 16 | vF << 16
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = (v7 & (1<<32)-1) >> 12 | v7 << 20
               v3 = v3 + v7 + W[row[8]]
               vF = vF ~ v3
               vF = (vF & (1<<32)-1) >> 8 | vF << 24
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = (v7 & (1<<32)-1) >> 7 | v7 << 25
               v0 = v0 + v5 + W[row[9]]
               vF = vF ~ v0
               vF = (vF & (1<<32)-1) >> 16 | vF << 16
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = (v5 & (1<<32)-1) >> 12 | v5 << 20
               v0 = v0 + v5 + W[row[10]]
               vF = vF ~ v0
               vF = (vF & (1<<32)-1) >> 8 | vF << 24
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = (v5 & (1<<32)-1) >> 7 | v5 << 25
               v1 = v1 + v6 + W[row[11]]
               vC = vC ~ v1
               vC = (vC & (1<<32)-1) >> 16 | vC << 16
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = (v6 & (1<<32)-1) >> 12 | v6 << 20
               v1 = v1 + v6 + W[row[12]]
               vC = vC ~ v1
               vC = (vC & (1<<32)-1) >> 8 | vC << 24
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = (v6 & (1<<32)-1) >> 7 | v6 << 25
               v2 = v2 + v7 + W[row[13]]
               vD = vD ~ v2
               vD = (vD & (1<<32)-1) >> 16 | vD << 16
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = (v7 & (1<<32)-1) >> 12 | v7 << 20
               v2 = v2 + v7 + W[row[14]]
               vD = vD ~ v2
               vD = (vD & (1<<32)-1) >> 8 | vD << 24
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = (v7 & (1<<32)-1) >> 7 | v7 << 25
               v3 = v3 + v4 + W[row[15]]
               vE = vE ~ v3
               vE = (vE & (1<<32)-1) >> 16 | vE << 16
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = (v4 & (1<<32)-1) >> 12 | v4 << 20
               v3 = v3 + v4 + W[row[16]]
               vE = vE ~ v3
               vE = (vE & (1<<32)-1) >> 8 | vE << 24
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = (v4 & (1<<32)-1) >> 7 | v4 << 25
            end
            h1 = h1 ~ v0 ~ v8
            h2 = h2 ~ v1 ~ v9
            h3 = h3 ~ v2 ~ vA
            h4 = h4 ~ v3 ~ vB
            h5 = h5 ~ v4 ~ vC
            h6 = h6 ~ v5 ~ vD
            h7 = h7 ~ v6 ~ vE
            h8 = h8 ~ v7 ~ vF
         end
         H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
         return bytes_compressed
      end

      local function blake2b_feed_128(H, _, str, offs, size, bytes_compressed, last_block_size, is_last_node)
         -- offs >= 0, size >= 0, size is multiple of 128
         local W = common_W
         local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
         for pos = offs + 1, offs + size, 128 do
            if str then
               W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
                  string_unpack("<i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8i8", str, pos)
            end
            local v0, v1, v2, v3, v4, v5, v6, v7 = h1, h2, h3, h4, h5, h6, h7, h8
            local v8, v9, vA, vB, vC, vD, vE, vF = sha2_H_lo[1], sha2_H_lo[2], sha2_H_lo[3], sha2_H_lo[4], sha2_H_lo[5], sha2_H_lo[6], sha2_H_lo[7], sha2_H_lo[8]
            bytes_compressed = bytes_compressed + (last_block_size or 128)
            vC = vC ~ bytes_compressed  -- t0 = low_8_bytes(bytes_compressed)
            -- t1 = high_8_bytes(bytes_compressed) = 0,  message length is always below 2^53 bytes
            if last_block_size then  -- flag f0
               vE = ~vE
            end
            if is_last_node then  -- flag f1
               vF = ~vF
            end
            for j = 1, 12 do
               local row = sigma[j]
               v0 = v0 + v4 + W[row[1]]
               vC = vC ~ v0
               vC = vC >> 32 | vC << 32
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = v4 >> 24 | v4 << 40
               v0 = v0 + v4 + W[row[2]]
               vC = vC ~ v0
               vC = vC >> 16 | vC << 48
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = v4 >> 63 | v4 << 1
               v1 = v1 + v5 + W[row[3]]
               vD = vD ~ v1
               vD = vD >> 32 | vD << 32
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = v5 >> 24 | v5 << 40
               v1 = v1 + v5 + W[row[4]]
               vD = vD ~ v1
               vD = vD >> 16 | vD << 48
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = v5 >> 63 | v5 << 1
               v2 = v2 + v6 + W[row[5]]
               vE = vE ~ v2
               vE = vE >> 32 | vE << 32
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = v6 >> 24 | v6 << 40
               v2 = v2 + v6 + W[row[6]]
               vE = vE ~ v2
               vE = vE >> 16 | vE << 48
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = v6 >> 63 | v6 << 1
               v3 = v3 + v7 + W[row[7]]
               vF = vF ~ v3
               vF = vF >> 32 | vF << 32
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = v7 >> 24 | v7 << 40
               v3 = v3 + v7 + W[row[8]]
               vF = vF ~ v3
               vF = vF >> 16 | vF << 48
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = v7 >> 63 | v7 << 1
               v0 = v0 + v5 + W[row[9]]
               vF = vF ~ v0
               vF = vF >> 32 | vF << 32
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = v5 >> 24 | v5 << 40
               v0 = v0 + v5 + W[row[10]]
               vF = vF ~ v0
               vF = vF >> 16 | vF << 48
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = v5 >> 63 | v5 << 1
               v1 = v1 + v6 + W[row[11]]
               vC = vC ~ v1
               vC = vC >> 32 | vC << 32
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = v6 >> 24 | v6 << 40
               v1 = v1 + v6 + W[row[12]]
               vC = vC ~ v1
               vC = vC >> 16 | vC << 48
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = v6 >> 63 | v6 << 1
               v2 = v2 + v7 + W[row[13]]
               vD = vD ~ v2
               vD = vD >> 32 | vD << 32
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = v7 >> 24 | v7 << 40
               v2 = v2 + v7 + W[row[14]]
               vD = vD ~ v2
               vD = vD >> 16 | vD << 48
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = v7 >> 63 | v7 << 1
               v3 = v3 + v4 + W[row[15]]
               vE = vE ~ v3
               vE = vE >> 32 | vE << 32
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = v4 >> 24 | v4 << 40
               v3 = v3 + v4 + W[row[16]]
               vE = vE ~ v3
               vE = vE >> 16 | vE << 48
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = v4 >> 63 | v4 << 1
            end
            h1 = h1 ~ v0 ~ v8
            h2 = h2 ~ v1 ~ v9
            h3 = h3 ~ v2 ~ vA
            h4 = h4 ~ v3 ~ vB
            h5 = h5 ~ v4 ~ vC
            h6 = h6 ~ v5 ~ vD
            h7 = h7 ~ v6 ~ vE
            h8 = h8 ~ v7 ~ vF
         end
         H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
         return bytes_compressed
      end

      local function blake3_feed_64(str, offs, size, flags, chunk_index, H_in, H_out, wide_output, block_length)
         -- offs >= 0, size >= 0, size is multiple of 64
         block_length = block_length or 64
         local W = common_W
         local h1, h2, h3, h4, h5, h6, h7, h8 = H_in[1], H_in[2], H_in[3], H_in[4], H_in[5], H_in[6], H_in[7], H_in[8]
         H_out = H_out or H_in
         for pos = offs + 1, offs + size, 64 do
            if str then
               W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
                  string_unpack("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4", str, pos)
            end
            local v0, v1, v2, v3, v4, v5, v6, v7 = h1, h2, h3, h4, h5, h6, h7, h8
            local v8, v9, vA, vB = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4]
            local t0 = chunk_index % 2^32         -- t0 = low_4_bytes(chunk_index)
            local t1 = (chunk_index - t0) / 2^32  -- t1 = high_4_bytes(chunk_index)
            local vC, vD, vE, vF = 0|t0, 0|t1, block_length, flags
            for j = 1, 7 do
               v0 = v0 + v4 + W[perm_blake3[j]]
               vC = vC ~ v0
               vC = (vC & (1<<32)-1) >> 16 | vC << 16
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = (v4 & (1<<32)-1) >> 12 | v4 << 20
               v0 = v0 + v4 + W[perm_blake3[j + 14]]
               vC = vC ~ v0
               vC = (vC & (1<<32)-1) >> 8 | vC << 24
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = (v4 & (1<<32)-1) >> 7 | v4 << 25
               v1 = v1 + v5 + W[perm_blake3[j + 1]]
               vD = vD ~ v1
               vD = (vD & (1<<32)-1) >> 16 | vD << 16
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = (v5 & (1<<32)-1) >> 12 | v5 << 20
               v1 = v1 + v5 + W[perm_blake3[j + 2]]
               vD = vD ~ v1
               vD = (vD & (1<<32)-1) >> 8 | vD << 24
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = (v5 & (1<<32)-1) >> 7 | v5 << 25
               v2 = v2 + v6 + W[perm_blake3[j + 16]]
               vE = vE ~ v2
               vE = (vE & (1<<32)-1) >> 16 | vE << 16
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = (v6 & (1<<32)-1) >> 12 | v6 << 20
               v2 = v2 + v6 + W[perm_blake3[j + 7]]
               vE = vE ~ v2
               vE = (vE & (1<<32)-1) >> 8 | vE << 24
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = (v6 & (1<<32)-1) >> 7 | v6 << 25
               v3 = v3 + v7 + W[perm_blake3[j + 15]]
               vF = vF ~ v3
               vF = (vF & (1<<32)-1) >> 16 | vF << 16
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = (v7 & (1<<32)-1) >> 12 | v7 << 20
               v3 = v3 + v7 + W[perm_blake3[j + 17]]
               vF = vF ~ v3
               vF = (vF & (1<<32)-1) >> 8 | vF << 24
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = (v7 & (1<<32)-1) >> 7 | v7 << 25
               v0 = v0 + v5 + W[perm_blake3[j + 21]]
               vF = vF ~ v0
               vF = (vF & (1<<32)-1) >> 16 | vF << 16
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = (v5 & (1<<32)-1) >> 12 | v5 << 20
               v0 = v0 + v5 + W[perm_blake3[j + 5]]
               vF = vF ~ v0
               vF = (vF & (1<<32)-1) >> 8 | vF << 24
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = (v5 & (1<<32)-1) >> 7 | v5 << 25
               v1 = v1 + v6 + W[perm_blake3[j + 3]]
               vC = vC ~ v1
               vC = (vC & (1<<32)-1) >> 16 | vC << 16
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = (v6 & (1<<32)-1) >> 12 | v6 << 20
               v1 = v1 + v6 + W[perm_blake3[j + 6]]
               vC = vC ~ v1
               vC = (vC & (1<<32)-1) >> 8 | vC << 24
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = (v6 & (1<<32)-1) >> 7 | v6 << 25
               v2 = v2 + v7 + W[perm_blake3[j + 4]]
               vD = vD ~ v2
               vD = (vD & (1<<32)-1) >> 16 | vD << 16
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = (v7 & (1<<32)-1) >> 12 | v7 << 20
               v2 = v2 + v7 + W[perm_blake3[j + 18]]
               vD = vD ~ v2
               vD = (vD & (1<<32)-1) >> 8 | vD << 24
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = (v7 & (1<<32)-1) >> 7 | v7 << 25
               v3 = v3 + v4 + W[perm_blake3[j + 19]]
               vE = vE ~ v3
               vE = (vE & (1<<32)-1) >> 16 | vE << 16
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = (v4 & (1<<32)-1) >> 12 | v4 << 20
               v3 = v3 + v4 + W[perm_blake3[j + 20]]
               vE = vE ~ v3
               vE = (vE & (1<<32)-1) >> 8 | vE << 24
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = (v4 & (1<<32)-1) >> 7 | v4 << 25
            end
            if wide_output then
               H_out[ 9] = h1 ~ v8
               H_out[10] = h2 ~ v9
               H_out[11] = h3 ~ vA
               H_out[12] = h4 ~ vB
               H_out[13] = h5 ~ vC
               H_out[14] = h6 ~ vD
               H_out[15] = h7 ~ vE
               H_out[16] = h8 ~ vF
            end
            h1 = v0 ~ v8
            h2 = v1 ~ v9
            h3 = v2 ~ vA
            h4 = v3 ~ vB
            h5 = v4 ~ vC
            h6 = v5 ~ vD
            h7 = v6 ~ vE
            h8 = v7 ~ vF
         end
         H_out[1], H_out[2], H_out[3], H_out[4], H_out[5], H_out[6], H_out[7], H_out[8] = h1, h2, h3, h4, h5, h6, h7, h8
      end

      return HEX64, XORA5, XOR_BYTE, sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed, blake2s_feed_64, blake2b_feed_128, blake3_feed_64
   ]=](md5_next_shift, md5_K, sha2_K_lo, sha2_K_hi, build_keccak_format, sha3_RC_lo, sigma, common_W, sha2_H_lo, sha2_H_hi, perm_blake3)

end


if branch == "INT32" then


	-- implementation for Lua 5.3/5.4 having non-standard numbers config "int32"+"double" (built with LUA_INT_TYPE=LUA_INT_INT)

	K_lo_modulo = 2^32

	function HEX(x) -- returns string of 8 lowercase hexadecimal digits
		return string_format("%08x", x)
	end

	XORA5, XOR_BYTE, sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed, blake2s_feed_64, blake2b_feed_128, blake3_feed_64 = load[=[-- branch "INT32"
      local md5_next_shift, md5_K, sha2_K_lo, sha2_K_hi, build_keccak_format, sha3_RC_lo, sha3_RC_hi, sigma, common_W, sha2_H_lo, sha2_H_hi, perm_blake3 = ...
      local string_unpack, floor = string.unpack, math.floor

      local function XORA5(x, y)
         return x ~ (y and (y + 2^31) % 2^32 - 2^31 or 0xA5A5A5A5)
      end

      local function XOR_BYTE(x, y)
         return x ~ y
      end

      local function sha256_feed_64(H, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W, K = common_W, sha2_K_hi
         local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
         for pos = offs + 1, offs + size, 64 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
               string_unpack(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4", str, pos)
            for j = 17, 64 do
               local a, b = W[j-15], W[j-2]
               W[j] = (a>>7 ~ a<<25 ~ a<<14 ~ a>>18 ~ a>>3) + (b<<15 ~ b>>17 ~ b<<13 ~ b>>19 ~ b>>10) + W[j-7] + W[j-16]
            end
            local a, b, c, d, e, f, g, h = h1, h2, h3, h4, h5, h6, h7, h8
            for j = 1, 64 do
               local z = (e>>6 ~ e<<26 ~ e>>11 ~ e<<21 ~ e>>25 ~ e<<7) + (g ~ e & (f ~ g)) + h + K[j] + W[j]
               h = g
               g = f
               f = e
               e = z + d
               d = c
               c = b
               b = a
               a = z + ((a ~ c) & d ~ a & c) + (a>>2 ~ a<<30 ~ a>>13 ~ a<<19 ~ a<<10 ~ a>>22)
            end
            h1 = a + h1
            h2 = b + h2
            h3 = c + h3
            h4 = d + h4
            h5 = e + h5
            h6 = f + h6
            h7 = g + h7
            h8 = h + h8
         end
         H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
      end

      local function sha512_feed_128(H_lo, H_hi, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 128
         -- W1_hi, W1_lo, W2_hi, W2_lo, ...   Wk_hi = W[2*k-1], Wk_lo = W[2*k]
         local floor, W, K_lo, K_hi = floor, common_W, sha2_K_lo, sha2_K_hi
         local h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
         local h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
         for pos = offs + 1, offs + size, 128 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16],
               W[17], W[18], W[19], W[20], W[21], W[22], W[23], W[24], W[25], W[26], W[27], W[28], W[29], W[30], W[31], W[32] =
               string_unpack(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4", str, pos)
            for jj = 17*2, 80*2, 2 do
               local a_lo, a_hi, b_lo, b_hi = W[jj-30], W[jj-31], W[jj-4], W[jj-5]
               local tmp =
                  (a_lo>>1 ~ a_hi<<31 ~ a_lo>>8 ~ a_hi<<24 ~ a_lo>>7 ~ a_hi<<25) % 2^32
                  + (b_lo>>19 ~ b_hi<<13 ~ b_lo<<3 ~ b_hi>>29 ~ b_lo>>6 ~ b_hi<<26) % 2^32
                  + W[jj-14] % 2^32 + W[jj-32] % 2^32
               W[jj-1] =
                  (a_hi>>1 ~ a_lo<<31 ~ a_hi>>8 ~ a_lo<<24 ~ a_hi>>7)
                  + (b_hi>>19 ~ b_lo<<13 ~ b_hi<<3 ~ b_lo>>29 ~ b_hi>>6)
                  + W[jj-15] + W[jj-33] + floor(tmp / 2^32)
               W[jj] = 0|((tmp + 2^31) % 2^32 - 2^31)
            end
            local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
            local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
            for j = 1, 80 do
               local jj = 2*j
               local z_lo = (e_lo>>14 ~ e_hi<<18 ~ e_lo>>18 ~ e_hi<<14 ~ e_lo<<23 ~ e_hi>>9) % 2^32 + (g_lo ~ e_lo & (f_lo ~ g_lo)) % 2^32 + h_lo % 2^32 + K_lo[j] + W[jj] % 2^32
               local z_hi = (e_hi>>14 ~ e_lo<<18 ~ e_hi>>18 ~ e_lo<<14 ~ e_hi<<23 ~ e_lo>>9) + (g_hi ~ e_hi & (f_hi ~ g_hi)) + h_hi + K_hi[j] + W[jj-1] + floor(z_lo / 2^32)
               z_lo = z_lo % 2^32
               h_lo = g_lo;  h_hi = g_hi
               g_lo = f_lo;  g_hi = f_hi
               f_lo = e_lo;  f_hi = e_hi
               e_lo = z_lo + d_lo % 2^32
               e_hi = z_hi + d_hi + floor(e_lo / 2^32)
               e_lo = 0|((e_lo + 2^31) % 2^32 - 2^31)
               d_lo = c_lo;  d_hi = c_hi
               c_lo = b_lo;  c_hi = b_hi
               b_lo = a_lo;  b_hi = a_hi
               z_lo = z_lo + (d_lo & c_lo ~ b_lo & (d_lo ~ c_lo)) % 2^32 + (b_lo>>28 ~ b_hi<<4 ~ b_lo<<30 ~ b_hi>>2 ~ b_lo<<25 ~ b_hi>>7) % 2^32
               a_hi = z_hi + (d_hi & c_hi ~ b_hi & (d_hi ~ c_hi)) + (b_hi>>28 ~ b_lo<<4 ~ b_hi<<30 ~ b_lo>>2 ~ b_hi<<25 ~ b_lo>>7) + floor(z_lo / 2^32)
               a_lo = 0|((z_lo + 2^31) % 2^32 - 2^31)
            end
            a_lo = h1_lo % 2^32 + a_lo % 2^32
            h1_hi = h1_hi + a_hi + floor(a_lo / 2^32)
            h1_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
            a_lo = h2_lo % 2^32 + b_lo % 2^32
            h2_hi = h2_hi + b_hi + floor(a_lo / 2^32)
            h2_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
            a_lo = h3_lo % 2^32 + c_lo % 2^32
            h3_hi = h3_hi + c_hi + floor(a_lo / 2^32)
            h3_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
            a_lo = h4_lo % 2^32 + d_lo % 2^32
            h4_hi = h4_hi + d_hi + floor(a_lo / 2^32)
            h4_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
            a_lo = h5_lo % 2^32 + e_lo % 2^32
            h5_hi = h5_hi + e_hi + floor(a_lo / 2^32)
            h5_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
            a_lo = h6_lo % 2^32 + f_lo % 2^32
            h6_hi = h6_hi + f_hi + floor(a_lo / 2^32)
            h6_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
            a_lo = h7_lo % 2^32 + g_lo % 2^32
            h7_hi = h7_hi + g_hi + floor(a_lo / 2^32)
            h7_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
            a_lo = h8_lo % 2^32 + h_lo % 2^32
            h8_hi = h8_hi + h_hi + floor(a_lo / 2^32)
            h8_lo = 0|((a_lo + 2^31) % 2^32 - 2^31)
         end
         H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
         H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
      end

      local function md5_feed_64(H, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W, K, md5_next_shift = common_W, md5_K, md5_next_shift
         local h1, h2, h3, h4 = H[1], H[2], H[3], H[4]
         for pos = offs + 1, offs + size, 64 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
               string_unpack("<i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4", str, pos)
            local a, b, c, d = h1, h2, h3, h4
            local s = 32-7
            for j = 1, 16 do
               local F = (d ~ b & (c ~ d)) + a + K[j] + W[j]
               a = d
               d = c
               c = b
               b = (F << 32-s | F>>s) + b
               s = md5_next_shift[s]
            end
            s = 32-5
            for j = 17, 32 do
               local F = (c ~ d & (b ~ c)) + a + K[j] + W[(5*j-4 & 15) + 1]
               a = d
               d = c
               c = b
               b = (F << 32-s | F>>s) + b
               s = md5_next_shift[s]
            end
            s = 32-4
            for j = 33, 48 do
               local F = (b ~ c ~ d) + a + K[j] + W[(3*j+2 & 15) + 1]
               a = d
               d = c
               c = b
               b = (F << 32-s | F>>s) + b
               s = md5_next_shift[s]
            end
            s = 32-6
            for j = 49, 64 do
               local F = (c ~ (b | ~d)) + a + K[j] + W[(j*7-7 & 15) + 1]
               a = d
               d = c
               c = b
               b = (F << 32-s | F>>s) + b
               s = md5_next_shift[s]
            end
            h1 = a + h1
            h2 = b + h2
            h3 = c + h3
            h4 = d + h4
         end
         H[1], H[2], H[3], H[4] = h1, h2, h3, h4
      end

      local function sha1_feed_64(H, str, offs, size)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W = common_W
         local h1, h2, h3, h4, h5 = H[1], H[2], H[3], H[4], H[5]
         for pos = offs + 1, offs + size, 64 do
            W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
               string_unpack(">i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4", str, pos)
            for j = 17, 80 do
               local a = W[j-3] ~ W[j-8] ~ W[j-14] ~ W[j-16]
               W[j] = a << 1 ~ a >> 31
            end
            local a, b, c, d, e = h1, h2, h3, h4, h5
            for j = 1, 20 do
               local z = (a << 5 ~ a >> 27) + (d ~ b & (c ~ d)) + 0x5A827999 + W[j] + e      -- constant = floor(2^30 * sqrt(2))
               e = d
               d = c
               c = b << 30 ~ b >> 2
               b = a
               a = z
            end
            for j = 21, 40 do
               local z = (a << 5 ~ a >> 27) + (b ~ c ~ d) + 0x6ED9EBA1 + W[j] + e            -- 2^30 * sqrt(3)
               e = d
               d = c
               c = b << 30 ~ b >> 2
               b = a
               a = z
            end
            for j = 41, 60 do
               local z = (a << 5 ~ a >> 27) + ((b ~ c) & d ~ b & c) + 0x8F1BBCDC + W[j] + e  -- 2^30 * sqrt(5)
               e = d
               d = c
               c = b << 30 ~ b >> 2
               b = a
               a = z
            end
            for j = 61, 80 do
               local z = (a << 5 ~ a >> 27) + (b ~ c ~ d) + 0xCA62C1D6 + W[j] + e            -- 2^30 * sqrt(10)
               e = d
               d = c
               c = b << 30 ~ b >> 2
               b = a
               a = z
            end
            h1 = a + h1
            h2 = b + h2
            h3 = c + h3
            h4 = d + h4
            h5 = e + h5
         end
         H[1], H[2], H[3], H[4], H[5] = h1, h2, h3, h4, h5
      end

      local keccak_format_i4i4 = build_keccak_format("i4i4")

      local function keccak_feed(lanes_lo, lanes_hi, str, offs, size, block_size_in_bytes)
         -- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8
         local RC_lo, RC_hi = sha3_RC_lo, sha3_RC_hi
         local qwords_qty = block_size_in_bytes / 8
         local keccak_format = keccak_format_i4i4[qwords_qty]
         for pos = offs + 1, offs + size, block_size_in_bytes do
            local dwords_from_message = {string_unpack(keccak_format, str, pos)}
            for j = 1, qwords_qty do
               lanes_lo[j] = lanes_lo[j] ~ dwords_from_message[2*j-1]
               lanes_hi[j] = lanes_hi[j] ~ dwords_from_message[2*j]
            end
            local L01_lo, L01_hi, L02_lo, L02_hi, L03_lo, L03_hi, L04_lo, L04_hi, L05_lo, L05_hi, L06_lo, L06_hi, L07_lo, L07_hi, L08_lo, L08_hi,
               L09_lo, L09_hi, L10_lo, L10_hi, L11_lo, L11_hi, L12_lo, L12_hi, L13_lo, L13_hi, L14_lo, L14_hi, L15_lo, L15_hi, L16_lo, L16_hi,
               L17_lo, L17_hi, L18_lo, L18_hi, L19_lo, L19_hi, L20_lo, L20_hi, L21_lo, L21_hi, L22_lo, L22_hi, L23_lo, L23_hi, L24_lo, L24_hi, L25_lo, L25_hi =
               lanes_lo[1], lanes_hi[1], lanes_lo[2], lanes_hi[2], lanes_lo[3], lanes_hi[3], lanes_lo[4], lanes_hi[4], lanes_lo[5], lanes_hi[5],
               lanes_lo[6], lanes_hi[6], lanes_lo[7], lanes_hi[7], lanes_lo[8], lanes_hi[8], lanes_lo[9], lanes_hi[9], lanes_lo[10], lanes_hi[10],
               lanes_lo[11], lanes_hi[11], lanes_lo[12], lanes_hi[12], lanes_lo[13], lanes_hi[13], lanes_lo[14], lanes_hi[14], lanes_lo[15], lanes_hi[15],
               lanes_lo[16], lanes_hi[16], lanes_lo[17], lanes_hi[17], lanes_lo[18], lanes_hi[18], lanes_lo[19], lanes_hi[19], lanes_lo[20], lanes_hi[20],
               lanes_lo[21], lanes_hi[21], lanes_lo[22], lanes_hi[22], lanes_lo[23], lanes_hi[23], lanes_lo[24], lanes_hi[24], lanes_lo[25], lanes_hi[25]
            for round_idx = 1, 24 do
               local C1_lo = L01_lo ~ L06_lo ~ L11_lo ~ L16_lo ~ L21_lo
               local C1_hi = L01_hi ~ L06_hi ~ L11_hi ~ L16_hi ~ L21_hi
               local C2_lo = L02_lo ~ L07_lo ~ L12_lo ~ L17_lo ~ L22_lo
               local C2_hi = L02_hi ~ L07_hi ~ L12_hi ~ L17_hi ~ L22_hi
               local C3_lo = L03_lo ~ L08_lo ~ L13_lo ~ L18_lo ~ L23_lo
               local C3_hi = L03_hi ~ L08_hi ~ L13_hi ~ L18_hi ~ L23_hi
               local C4_lo = L04_lo ~ L09_lo ~ L14_lo ~ L19_lo ~ L24_lo
               local C4_hi = L04_hi ~ L09_hi ~ L14_hi ~ L19_hi ~ L24_hi
               local C5_lo = L05_lo ~ L10_lo ~ L15_lo ~ L20_lo ~ L25_lo
               local C5_hi = L05_hi ~ L10_hi ~ L15_hi ~ L20_hi ~ L25_hi
               local D_lo = C1_lo ~ C3_lo<<1 ~ C3_hi>>31
               local D_hi = C1_hi ~ C3_hi<<1 ~ C3_lo>>31
               local T0_lo = D_lo ~ L02_lo
               local T0_hi = D_hi ~ L02_hi
               local T1_lo = D_lo ~ L07_lo
               local T1_hi = D_hi ~ L07_hi
               local T2_lo = D_lo ~ L12_lo
               local T2_hi = D_hi ~ L12_hi
               local T3_lo = D_lo ~ L17_lo
               local T3_hi = D_hi ~ L17_hi
               local T4_lo = D_lo ~ L22_lo
               local T4_hi = D_hi ~ L22_hi
               L02_lo = T1_lo>>20 ~ T1_hi<<12
               L02_hi = T1_hi>>20 ~ T1_lo<<12
               L07_lo = T3_lo>>19 ~ T3_hi<<13
               L07_hi = T3_hi>>19 ~ T3_lo<<13
               L12_lo = T0_lo<<1 ~ T0_hi>>31
               L12_hi = T0_hi<<1 ~ T0_lo>>31
               L17_lo = T2_lo<<10 ~ T2_hi>>22
               L17_hi = T2_hi<<10 ~ T2_lo>>22
               L22_lo = T4_lo<<2 ~ T4_hi>>30
               L22_hi = T4_hi<<2 ~ T4_lo>>30
               D_lo = C2_lo ~ C4_lo<<1 ~ C4_hi>>31
               D_hi = C2_hi ~ C4_hi<<1 ~ C4_lo>>31
               T0_lo = D_lo ~ L03_lo
               T0_hi = D_hi ~ L03_hi
               T1_lo = D_lo ~ L08_lo
               T1_hi = D_hi ~ L08_hi
               T2_lo = D_lo ~ L13_lo
               T2_hi = D_hi ~ L13_hi
               T3_lo = D_lo ~ L18_lo
               T3_hi = D_hi ~ L18_hi
               T4_lo = D_lo ~ L23_lo
               T4_hi = D_hi ~ L23_hi
               L03_lo = T2_lo>>21 ~ T2_hi<<11
               L03_hi = T2_hi>>21 ~ T2_lo<<11
               L08_lo = T4_lo>>3 ~ T4_hi<<29
               L08_hi = T4_hi>>3 ~ T4_lo<<29
               L13_lo = T1_lo<<6 ~ T1_hi>>26
               L13_hi = T1_hi<<6 ~ T1_lo>>26
               L18_lo = T3_lo<<15 ~ T3_hi>>17
               L18_hi = T3_hi<<15 ~ T3_lo>>17
               L23_lo = T0_lo>>2 ~ T0_hi<<30
               L23_hi = T0_hi>>2 ~ T0_lo<<30
               D_lo = C3_lo ~ C5_lo<<1 ~ C5_hi>>31
               D_hi = C3_hi ~ C5_hi<<1 ~ C5_lo>>31
               T0_lo = D_lo ~ L04_lo
               T0_hi = D_hi ~ L04_hi
               T1_lo = D_lo ~ L09_lo
               T1_hi = D_hi ~ L09_hi
               T2_lo = D_lo ~ L14_lo
               T2_hi = D_hi ~ L14_hi
               T3_lo = D_lo ~ L19_lo
               T3_hi = D_hi ~ L19_hi
               T4_lo = D_lo ~ L24_lo
               T4_hi = D_hi ~ L24_hi
               L04_lo = T3_lo<<21 ~ T3_hi>>11
               L04_hi = T3_hi<<21 ~ T3_lo>>11
               L09_lo = T0_lo<<28 ~ T0_hi>>4
               L09_hi = T0_hi<<28 ~ T0_lo>>4
               L14_lo = T2_lo<<25 ~ T2_hi>>7
               L14_hi = T2_hi<<25 ~ T2_lo>>7
               L19_lo = T4_lo>>8 ~ T4_hi<<24
               L19_hi = T4_hi>>8 ~ T4_lo<<24
               L24_lo = T1_lo>>9 ~ T1_hi<<23
               L24_hi = T1_hi>>9 ~ T1_lo<<23
               D_lo = C4_lo ~ C1_lo<<1 ~ C1_hi>>31
               D_hi = C4_hi ~ C1_hi<<1 ~ C1_lo>>31
               T0_lo = D_lo ~ L05_lo
               T0_hi = D_hi ~ L05_hi
               T1_lo = D_lo ~ L10_lo
               T1_hi = D_hi ~ L10_hi
               T2_lo = D_lo ~ L15_lo
               T2_hi = D_hi ~ L15_hi
               T3_lo = D_lo ~ L20_lo
               T3_hi = D_hi ~ L20_hi
               T4_lo = D_lo ~ L25_lo
               T4_hi = D_hi ~ L25_hi
               L05_lo = T4_lo<<14 ~ T4_hi>>18
               L05_hi = T4_hi<<14 ~ T4_lo>>18
               L10_lo = T1_lo<<20 ~ T1_hi>>12
               L10_hi = T1_hi<<20 ~ T1_lo>>12
               L15_lo = T3_lo<<8 ~ T3_hi>>24
               L15_hi = T3_hi<<8 ~ T3_lo>>24
               L20_lo = T0_lo<<27 ~ T0_hi>>5
               L20_hi = T0_hi<<27 ~ T0_lo>>5
               L25_lo = T2_lo>>25 ~ T2_hi<<7
               L25_hi = T2_hi>>25 ~ T2_lo<<7
               D_lo = C5_lo ~ C2_lo<<1 ~ C2_hi>>31
               D_hi = C5_hi ~ C2_hi<<1 ~ C2_lo>>31
               T1_lo = D_lo ~ L06_lo
               T1_hi = D_hi ~ L06_hi
               T2_lo = D_lo ~ L11_lo
               T2_hi = D_hi ~ L11_hi
               T3_lo = D_lo ~ L16_lo
               T3_hi = D_hi ~ L16_hi
               T4_lo = D_lo ~ L21_lo
               T4_hi = D_hi ~ L21_hi
               L06_lo = T2_lo<<3 ~ T2_hi>>29
               L06_hi = T2_hi<<3 ~ T2_lo>>29
               L11_lo = T4_lo<<18 ~ T4_hi>>14
               L11_hi = T4_hi<<18 ~ T4_lo>>14
               L16_lo = T1_lo>>28 ~ T1_hi<<4
               L16_hi = T1_hi>>28 ~ T1_lo<<4
               L21_lo = T3_lo>>23 ~ T3_hi<<9
               L21_hi = T3_hi>>23 ~ T3_lo<<9
               L01_lo = D_lo ~ L01_lo
               L01_hi = D_hi ~ L01_hi
               L01_lo, L02_lo, L03_lo, L04_lo, L05_lo = L01_lo ~ ~L02_lo & L03_lo, L02_lo ~ ~L03_lo & L04_lo, L03_lo ~ ~L04_lo & L05_lo, L04_lo ~ ~L05_lo & L01_lo, L05_lo ~ ~L01_lo & L02_lo
               L01_hi, L02_hi, L03_hi, L04_hi, L05_hi = L01_hi ~ ~L02_hi & L03_hi, L02_hi ~ ~L03_hi & L04_hi, L03_hi ~ ~L04_hi & L05_hi, L04_hi ~ ~L05_hi & L01_hi, L05_hi ~ ~L01_hi & L02_hi
               L06_lo, L07_lo, L08_lo, L09_lo, L10_lo = L09_lo ~ ~L10_lo & L06_lo, L10_lo ~ ~L06_lo & L07_lo, L06_lo ~ ~L07_lo & L08_lo, L07_lo ~ ~L08_lo & L09_lo, L08_lo ~ ~L09_lo & L10_lo
               L06_hi, L07_hi, L08_hi, L09_hi, L10_hi = L09_hi ~ ~L10_hi & L06_hi, L10_hi ~ ~L06_hi & L07_hi, L06_hi ~ ~L07_hi & L08_hi, L07_hi ~ ~L08_hi & L09_hi, L08_hi ~ ~L09_hi & L10_hi
               L11_lo, L12_lo, L13_lo, L14_lo, L15_lo = L12_lo ~ ~L13_lo & L14_lo, L13_lo ~ ~L14_lo & L15_lo, L14_lo ~ ~L15_lo & L11_lo, L15_lo ~ ~L11_lo & L12_lo, L11_lo ~ ~L12_lo & L13_lo
               L11_hi, L12_hi, L13_hi, L14_hi, L15_hi = L12_hi ~ ~L13_hi & L14_hi, L13_hi ~ ~L14_hi & L15_hi, L14_hi ~ ~L15_hi & L11_hi, L15_hi ~ ~L11_hi & L12_hi, L11_hi ~ ~L12_hi & L13_hi
               L16_lo, L17_lo, L18_lo, L19_lo, L20_lo = L20_lo ~ ~L16_lo & L17_lo, L16_lo ~ ~L17_lo & L18_lo, L17_lo ~ ~L18_lo & L19_lo, L18_lo ~ ~L19_lo & L20_lo, L19_lo ~ ~L20_lo & L16_lo
               L16_hi, L17_hi, L18_hi, L19_hi, L20_hi = L20_hi ~ ~L16_hi & L17_hi, L16_hi ~ ~L17_hi & L18_hi, L17_hi ~ ~L18_hi & L19_hi, L18_hi ~ ~L19_hi & L20_hi, L19_hi ~ ~L20_hi & L16_hi
               L21_lo, L22_lo, L23_lo, L24_lo, L25_lo = L23_lo ~ ~L24_lo & L25_lo, L24_lo ~ ~L25_lo & L21_lo, L25_lo ~ ~L21_lo & L22_lo, L21_lo ~ ~L22_lo & L23_lo, L22_lo ~ ~L23_lo & L24_lo
               L21_hi, L22_hi, L23_hi, L24_hi, L25_hi = L23_hi ~ ~L24_hi & L25_hi, L24_hi ~ ~L25_hi & L21_hi, L25_hi ~ ~L21_hi & L22_hi, L21_hi ~ ~L22_hi & L23_hi, L22_hi ~ ~L23_hi & L24_hi
               L01_lo = L01_lo ~ RC_lo[round_idx]
               L01_hi = L01_hi ~ RC_hi[round_idx]
            end
            lanes_lo[1]  = L01_lo;  lanes_hi[1]  = L01_hi
            lanes_lo[2]  = L02_lo;  lanes_hi[2]  = L02_hi
            lanes_lo[3]  = L03_lo;  lanes_hi[3]  = L03_hi
            lanes_lo[4]  = L04_lo;  lanes_hi[4]  = L04_hi
            lanes_lo[5]  = L05_lo;  lanes_hi[5]  = L05_hi
            lanes_lo[6]  = L06_lo;  lanes_hi[6]  = L06_hi
            lanes_lo[7]  = L07_lo;  lanes_hi[7]  = L07_hi
            lanes_lo[8]  = L08_lo;  lanes_hi[8]  = L08_hi
            lanes_lo[9]  = L09_lo;  lanes_hi[9]  = L09_hi
            lanes_lo[10] = L10_lo;  lanes_hi[10] = L10_hi
            lanes_lo[11] = L11_lo;  lanes_hi[11] = L11_hi
            lanes_lo[12] = L12_lo;  lanes_hi[12] = L12_hi
            lanes_lo[13] = L13_lo;  lanes_hi[13] = L13_hi
            lanes_lo[14] = L14_lo;  lanes_hi[14] = L14_hi
            lanes_lo[15] = L15_lo;  lanes_hi[15] = L15_hi
            lanes_lo[16] = L16_lo;  lanes_hi[16] = L16_hi
            lanes_lo[17] = L17_lo;  lanes_hi[17] = L17_hi
            lanes_lo[18] = L18_lo;  lanes_hi[18] = L18_hi
            lanes_lo[19] = L19_lo;  lanes_hi[19] = L19_hi
            lanes_lo[20] = L20_lo;  lanes_hi[20] = L20_hi
            lanes_lo[21] = L21_lo;  lanes_hi[21] = L21_hi
            lanes_lo[22] = L22_lo;  lanes_hi[22] = L22_hi
            lanes_lo[23] = L23_lo;  lanes_hi[23] = L23_hi
            lanes_lo[24] = L24_lo;  lanes_hi[24] = L24_hi
            lanes_lo[25] = L25_lo;  lanes_hi[25] = L25_hi
         end
      end

      local function blake2s_feed_64(H, str, offs, size, bytes_compressed, last_block_size, is_last_node)
         -- offs >= 0, size >= 0, size is multiple of 64
         local W = common_W
         local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
         for pos = offs + 1, offs + size, 64 do
            if str then
               W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
                  string_unpack("<i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4", str, pos)
            end
            local v0, v1, v2, v3, v4, v5, v6, v7 = h1, h2, h3, h4, h5, h6, h7, h8
            local v8, v9, vA, vB, vC, vD, vE, vF = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4], sha2_H_hi[5], sha2_H_hi[6], sha2_H_hi[7], sha2_H_hi[8]
            bytes_compressed = bytes_compressed + (last_block_size or 64)
            local t0 = bytes_compressed % 2^32
            local t1 = (bytes_compressed - t0) / 2^32
            t0 = (t0 + 2^31) % 2^32 - 2^31  -- convert to int32 range (-2^31)..(2^31-1) to avoid "number has no integer representation" error while XORing
            vC = vC ~ t0  -- t0 = low_4_bytes(bytes_compressed)
            vD = vD ~ t1  -- t1 = high_4_bytes(bytes_compressed)
            if last_block_size then  -- flag f0
               vE = ~vE
            end
            if is_last_node then  -- flag f1
               vF = ~vF
            end
            for j = 1, 10 do
               local row = sigma[j]
               v0 = v0 + v4 + W[row[1]]
               vC = vC ~ v0
               vC = vC >> 16 | vC << 16
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = v4 >> 12 | v4 << 20
               v0 = v0 + v4 + W[row[2]]
               vC = vC ~ v0
               vC = vC >> 8 | vC << 24
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = v4 >> 7 | v4 << 25
               v1 = v1 + v5 + W[row[3]]
               vD = vD ~ v1
               vD = vD >> 16 | vD << 16
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = v5 >> 12 | v5 << 20
               v1 = v1 + v5 + W[row[4]]
               vD = vD ~ v1
               vD = vD >> 8 | vD << 24
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = v5 >> 7 | v5 << 25
               v2 = v2 + v6 + W[row[5]]
               vE = vE ~ v2
               vE = vE >> 16 | vE << 16
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = v6 >> 12 | v6 << 20
               v2 = v2 + v6 + W[row[6]]
               vE = vE ~ v2
               vE = vE >> 8 | vE << 24
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = v6 >> 7 | v6 << 25
               v3 = v3 + v7 + W[row[7]]
               vF = vF ~ v3
               vF = vF >> 16 | vF << 16
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = v7 >> 12 | v7 << 20
               v3 = v3 + v7 + W[row[8]]
               vF = vF ~ v3
               vF = vF >> 8 | vF << 24
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = v7 >> 7 | v7 << 25
               v0 = v0 + v5 + W[row[9]]
               vF = vF ~ v0
               vF = vF >> 16 | vF << 16
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = v5 >> 12 | v5 << 20
               v0 = v0 + v5 + W[row[10]]
               vF = vF ~ v0
               vF = vF >> 8 | vF << 24
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = v5 >> 7 | v5 << 25
               v1 = v1 + v6 + W[row[11]]
               vC = vC ~ v1
               vC = vC >> 16 | vC << 16
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = v6 >> 12 | v6 << 20
               v1 = v1 + v6 + W[row[12]]
               vC = vC ~ v1
               vC = vC >> 8 | vC << 24
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = v6 >> 7 | v6 << 25
               v2 = v2 + v7 + W[row[13]]
               vD = vD ~ v2
               vD = vD >> 16 | vD << 16
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = v7 >> 12 | v7 << 20
               v2 = v2 + v7 + W[row[14]]
               vD = vD ~ v2
               vD = vD >> 8 | vD << 24
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = v7 >> 7 | v7 << 25
               v3 = v3 + v4 + W[row[15]]
               vE = vE ~ v3
               vE = vE >> 16 | vE << 16
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = v4 >> 12 | v4 << 20
               v3 = v3 + v4 + W[row[16]]
               vE = vE ~ v3
               vE = vE >> 8 | vE << 24
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = v4 >> 7 | v4 << 25
            end
            h1 = h1 ~ v0 ~ v8
            h2 = h2 ~ v1 ~ v9
            h3 = h3 ~ v2 ~ vA
            h4 = h4 ~ v3 ~ vB
            h5 = h5 ~ v4 ~ vC
            h6 = h6 ~ v5 ~ vD
            h7 = h7 ~ v6 ~ vE
            h8 = h8 ~ v7 ~ vF
         end
         H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
         return bytes_compressed
      end

      local function blake2b_feed_128(H_lo, H_hi, str, offs, size, bytes_compressed, last_block_size, is_last_node)
         -- offs >= 0, size >= 0, size is multiple of 128
         local W = common_W
         local h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
         local h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
         for pos = offs + 1, offs + size, 128 do
            if str then
               W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16],
               W[17], W[18], W[19], W[20], W[21], W[22], W[23], W[24], W[25], W[26], W[27], W[28], W[29], W[30], W[31], W[32] =
                  string_unpack("<i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4", str, pos)
            end
            local v0_lo, v1_lo, v2_lo, v3_lo, v4_lo, v5_lo, v6_lo, v7_lo = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
            local v0_hi, v1_hi, v2_hi, v3_hi, v4_hi, v5_hi, v6_hi, v7_hi = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
            local v8_lo, v9_lo, vA_lo, vB_lo, vC_lo, vD_lo, vE_lo, vF_lo = sha2_H_lo[1], sha2_H_lo[2], sha2_H_lo[3], sha2_H_lo[4], sha2_H_lo[5], sha2_H_lo[6], sha2_H_lo[7], sha2_H_lo[8]
            local v8_hi, v9_hi, vA_hi, vB_hi, vC_hi, vD_hi, vE_hi, vF_hi = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4], sha2_H_hi[5], sha2_H_hi[6], sha2_H_hi[7], sha2_H_hi[8]
            bytes_compressed = bytes_compressed + (last_block_size or 128)
            local t0_lo = bytes_compressed % 2^32
            local t0_hi = (bytes_compressed - t0_lo) / 2^32
            t0_lo = (t0_lo + 2^31) % 2^32 - 2^31  -- convert to int32 range (-2^31)..(2^31-1) to avoid "number has no integer representation" error while XORing
            vC_lo = vC_lo ~ t0_lo  -- t0 = low_8_bytes(bytes_compressed)
            vC_hi = vC_hi ~ t0_hi
            -- t1 = high_8_bytes(bytes_compressed) = 0,  message length is always below 2^53 bytes
            if last_block_size then  -- flag f0
               vE_lo = ~vE_lo
               vE_hi = ~vE_hi
            end
            if is_last_node then  -- flag f1
               vF_lo = ~vF_lo
               vF_hi = ~vF_hi
            end
            for j = 1, 12 do
               local row = sigma[j]
               local k = row[1] * 2
               v0_lo = v0_lo % 2^32 + v4_lo % 2^32 + W[k-1] % 2^32
               v0_hi = v0_hi + v4_hi + floor(v0_lo / 2^32) + W[k]
               v0_lo = 0|((v0_lo + 2^31) % 2^32 - 2^31)
               vC_lo, vC_hi = vC_hi ~ v0_hi, vC_lo ~ v0_lo
               v8_lo = v8_lo % 2^32 + vC_lo % 2^32
               v8_hi = v8_hi + vC_hi + floor(v8_lo / 2^32)
               v8_lo = 0|((v8_lo + 2^31) % 2^32 - 2^31)
               v4_lo, v4_hi = v4_lo ~ v8_lo, v4_hi ~ v8_hi
               v4_lo, v4_hi = v4_lo >> 24 | v4_hi << 8, v4_hi >> 24 | v4_lo << 8
               k = row[2] * 2
               v0_lo = v0_lo % 2^32 + v4_lo % 2^32 + W[k-1] % 2^32
               v0_hi = v0_hi + v4_hi + floor(v0_lo / 2^32) + W[k]
               v0_lo = 0|((v0_lo + 2^31) % 2^32 - 2^31)
               vC_lo, vC_hi = vC_lo ~ v0_lo, vC_hi ~ v0_hi
               vC_lo, vC_hi = vC_lo >> 16 | vC_hi << 16, vC_hi >> 16 | vC_lo << 16
               v8_lo = v8_lo % 2^32 + vC_lo % 2^32
               v8_hi = v8_hi + vC_hi + floor(v8_lo / 2^32)
               v8_lo = 0|((v8_lo + 2^31) % 2^32 - 2^31)
               v4_lo, v4_hi = v4_lo ~ v8_lo, v4_hi ~ v8_hi
               v4_lo, v4_hi = v4_lo << 1 | v4_hi >> 31, v4_hi << 1 | v4_lo >> 31
               k = row[3] * 2
               v1_lo = v1_lo % 2^32 + v5_lo % 2^32 + W[k-1] % 2^32
               v1_hi = v1_hi + v5_hi + floor(v1_lo / 2^32) + W[k]
               v1_lo = 0|((v1_lo + 2^31) % 2^32 - 2^31)
               vD_lo, vD_hi = vD_hi ~ v1_hi, vD_lo ~ v1_lo
               v9_lo = v9_lo % 2^32 + vD_lo % 2^32
               v9_hi = v9_hi + vD_hi + floor(v9_lo / 2^32)
               v9_lo = 0|((v9_lo + 2^31) % 2^32 - 2^31)
               v5_lo, v5_hi = v5_lo ~ v9_lo, v5_hi ~ v9_hi
               v5_lo, v5_hi = v5_lo >> 24 | v5_hi << 8, v5_hi >> 24 | v5_lo << 8
               k = row[4] * 2
               v1_lo = v1_lo % 2^32 + v5_lo % 2^32 + W[k-1] % 2^32
               v1_hi = v1_hi + v5_hi + floor(v1_lo / 2^32) + W[k]
               v1_lo = 0|((v1_lo + 2^31) % 2^32 - 2^31)
               vD_lo, vD_hi = vD_lo ~ v1_lo, vD_hi ~ v1_hi
               vD_lo, vD_hi = vD_lo >> 16 | vD_hi << 16, vD_hi >> 16 | vD_lo << 16
               v9_lo = v9_lo % 2^32 + vD_lo % 2^32
               v9_hi = v9_hi + vD_hi + floor(v9_lo / 2^32)
               v9_lo = 0|((v9_lo + 2^31) % 2^32 - 2^31)
               v5_lo, v5_hi = v5_lo ~ v9_lo, v5_hi ~ v9_hi
               v5_lo, v5_hi = v5_lo << 1 | v5_hi >> 31, v5_hi << 1 | v5_lo >> 31
               k = row[5] * 2
               v2_lo = v2_lo % 2^32 + v6_lo % 2^32 + W[k-1] % 2^32
               v2_hi = v2_hi + v6_hi + floor(v2_lo / 2^32) + W[k]
               v2_lo = 0|((v2_lo + 2^31) % 2^32 - 2^31)
               vE_lo, vE_hi = vE_hi ~ v2_hi, vE_lo ~ v2_lo
               vA_lo = vA_lo % 2^32 + vE_lo % 2^32
               vA_hi = vA_hi + vE_hi + floor(vA_lo / 2^32)
               vA_lo = 0|((vA_lo + 2^31) % 2^32 - 2^31)
               v6_lo, v6_hi = v6_lo ~ vA_lo, v6_hi ~ vA_hi
               v6_lo, v6_hi = v6_lo >> 24 | v6_hi << 8, v6_hi >> 24 | v6_lo << 8
               k = row[6] * 2
               v2_lo = v2_lo % 2^32 + v6_lo % 2^32 + W[k-1] % 2^32
               v2_hi = v2_hi + v6_hi + floor(v2_lo / 2^32) + W[k]
               v2_lo = 0|((v2_lo + 2^31) % 2^32 - 2^31)
               vE_lo, vE_hi = vE_lo ~ v2_lo, vE_hi ~ v2_hi
               vE_lo, vE_hi = vE_lo >> 16 | vE_hi << 16, vE_hi >> 16 | vE_lo << 16
               vA_lo = vA_lo % 2^32 + vE_lo % 2^32
               vA_hi = vA_hi + vE_hi + floor(vA_lo / 2^32)
               vA_lo = 0|((vA_lo + 2^31) % 2^32 - 2^31)
               v6_lo, v6_hi = v6_lo ~ vA_lo, v6_hi ~ vA_hi
               v6_lo, v6_hi = v6_lo << 1 | v6_hi >> 31, v6_hi << 1 | v6_lo >> 31
               k = row[7] * 2
               v3_lo = v3_lo % 2^32 + v7_lo % 2^32 + W[k-1] % 2^32
               v3_hi = v3_hi + v7_hi + floor(v3_lo / 2^32) + W[k]
               v3_lo = 0|((v3_lo + 2^31) % 2^32 - 2^31)
               vF_lo, vF_hi = vF_hi ~ v3_hi, vF_lo ~ v3_lo
               vB_lo = vB_lo % 2^32 + vF_lo % 2^32
               vB_hi = vB_hi + vF_hi + floor(vB_lo / 2^32)
               vB_lo = 0|((vB_lo + 2^31) % 2^32 - 2^31)
               v7_lo, v7_hi = v7_lo ~ vB_lo, v7_hi ~ vB_hi
               v7_lo, v7_hi = v7_lo >> 24 | v7_hi << 8, v7_hi >> 24 | v7_lo << 8
               k = row[8] * 2
               v3_lo = v3_lo % 2^32 + v7_lo % 2^32 + W[k-1] % 2^32
               v3_hi = v3_hi + v7_hi + floor(v3_lo / 2^32) + W[k]
               v3_lo = 0|((v3_lo + 2^31) % 2^32 - 2^31)
               vF_lo, vF_hi = vF_lo ~ v3_lo, vF_hi ~ v3_hi
               vF_lo, vF_hi = vF_lo >> 16 | vF_hi << 16, vF_hi >> 16 | vF_lo << 16
               vB_lo = vB_lo % 2^32 + vF_lo % 2^32
               vB_hi = vB_hi + vF_hi + floor(vB_lo / 2^32)
               vB_lo = 0|((vB_lo + 2^31) % 2^32 - 2^31)
               v7_lo, v7_hi = v7_lo ~ vB_lo, v7_hi ~ vB_hi
               v7_lo, v7_hi = v7_lo << 1 | v7_hi >> 31, v7_hi << 1 | v7_lo >> 31
               k = row[9] * 2
               v0_lo = v0_lo % 2^32 + v5_lo % 2^32 + W[k-1] % 2^32
               v0_hi = v0_hi + v5_hi + floor(v0_lo / 2^32) + W[k]
               v0_lo = 0|((v0_lo + 2^31) % 2^32 - 2^31)
               vF_lo, vF_hi = vF_hi ~ v0_hi, vF_lo ~ v0_lo
               vA_lo = vA_lo % 2^32 + vF_lo % 2^32
               vA_hi = vA_hi + vF_hi + floor(vA_lo / 2^32)
               vA_lo = 0|((vA_lo + 2^31) % 2^32 - 2^31)
               v5_lo, v5_hi = v5_lo ~ vA_lo, v5_hi ~ vA_hi
               v5_lo, v5_hi = v5_lo >> 24 | v5_hi << 8, v5_hi >> 24 | v5_lo << 8
               k = row[10] * 2
               v0_lo = v0_lo % 2^32 + v5_lo % 2^32 + W[k-1] % 2^32
               v0_hi = v0_hi + v5_hi + floor(v0_lo / 2^32) + W[k]
               v0_lo = 0|((v0_lo + 2^31) % 2^32 - 2^31)
               vF_lo, vF_hi = vF_lo ~ v0_lo, vF_hi ~ v0_hi
               vF_lo, vF_hi = vF_lo >> 16 | vF_hi << 16, vF_hi >> 16 | vF_lo << 16
               vA_lo = vA_lo % 2^32 + vF_lo % 2^32
               vA_hi = vA_hi + vF_hi + floor(vA_lo / 2^32)
               vA_lo = 0|((vA_lo + 2^31) % 2^32 - 2^31)
               v5_lo, v5_hi = v5_lo ~ vA_lo, v5_hi ~ vA_hi
               v5_lo, v5_hi = v5_lo << 1 | v5_hi >> 31, v5_hi << 1 | v5_lo >> 31
               k = row[11] * 2
               v1_lo = v1_lo % 2^32 + v6_lo % 2^32 + W[k-1] % 2^32
               v1_hi = v1_hi + v6_hi + floor(v1_lo / 2^32) + W[k]
               v1_lo = 0|((v1_lo + 2^31) % 2^32 - 2^31)
               vC_lo, vC_hi = vC_hi ~ v1_hi, vC_lo ~ v1_lo
               vB_lo = vB_lo % 2^32 + vC_lo % 2^32
               vB_hi = vB_hi + vC_hi + floor(vB_lo / 2^32)
               vB_lo = 0|((vB_lo + 2^31) % 2^32 - 2^31)
               v6_lo, v6_hi = v6_lo ~ vB_lo, v6_hi ~ vB_hi
               v6_lo, v6_hi = v6_lo >> 24 | v6_hi << 8, v6_hi >> 24 | v6_lo << 8
               k = row[12] * 2
               v1_lo = v1_lo % 2^32 + v6_lo % 2^32 + W[k-1] % 2^32
               v1_hi = v1_hi + v6_hi + floor(v1_lo / 2^32) + W[k]
               v1_lo = 0|((v1_lo + 2^31) % 2^32 - 2^31)
               vC_lo, vC_hi = vC_lo ~ v1_lo, vC_hi ~ v1_hi
               vC_lo, vC_hi = vC_lo >> 16 | vC_hi << 16, vC_hi >> 16 | vC_lo << 16
               vB_lo = vB_lo % 2^32 + vC_lo % 2^32
               vB_hi = vB_hi + vC_hi + floor(vB_lo / 2^32)
               vB_lo = 0|((vB_lo + 2^31) % 2^32 - 2^31)
               v6_lo, v6_hi = v6_lo ~ vB_lo, v6_hi ~ vB_hi
               v6_lo, v6_hi = v6_lo << 1 | v6_hi >> 31, v6_hi << 1 | v6_lo >> 31
               k = row[13] * 2
               v2_lo = v2_lo % 2^32 + v7_lo % 2^32 + W[k-1] % 2^32
               v2_hi = v2_hi + v7_hi + floor(v2_lo / 2^32) + W[k]
               v2_lo = 0|((v2_lo + 2^31) % 2^32 - 2^31)
               vD_lo, vD_hi = vD_hi ~ v2_hi, vD_lo ~ v2_lo
               v8_lo = v8_lo % 2^32 + vD_lo % 2^32
               v8_hi = v8_hi + vD_hi + floor(v8_lo / 2^32)
               v8_lo = 0|((v8_lo + 2^31) % 2^32 - 2^31)
               v7_lo, v7_hi = v7_lo ~ v8_lo, v7_hi ~ v8_hi
               v7_lo, v7_hi = v7_lo >> 24 | v7_hi << 8, v7_hi >> 24 | v7_lo << 8
               k = row[14] * 2
               v2_lo = v2_lo % 2^32 + v7_lo % 2^32 + W[k-1] % 2^32
               v2_hi = v2_hi + v7_hi + floor(v2_lo / 2^32) + W[k]
               v2_lo = 0|((v2_lo + 2^31) % 2^32 - 2^31)
               vD_lo, vD_hi = vD_lo ~ v2_lo, vD_hi ~ v2_hi
               vD_lo, vD_hi = vD_lo >> 16 | vD_hi << 16, vD_hi >> 16 | vD_lo << 16
               v8_lo = v8_lo % 2^32 + vD_lo % 2^32
               v8_hi = v8_hi + vD_hi + floor(v8_lo / 2^32)
               v8_lo = 0|((v8_lo + 2^31) % 2^32 - 2^31)
               v7_lo, v7_hi = v7_lo ~ v8_lo, v7_hi ~ v8_hi
               v7_lo, v7_hi = v7_lo << 1 | v7_hi >> 31, v7_hi << 1 | v7_lo >> 31
               k = row[15] * 2
               v3_lo = v3_lo % 2^32 + v4_lo % 2^32 + W[k-1] % 2^32
               v3_hi = v3_hi + v4_hi + floor(v3_lo / 2^32) + W[k]
               v3_lo = 0|((v3_lo + 2^31) % 2^32 - 2^31)
               vE_lo, vE_hi = vE_hi ~ v3_hi, vE_lo ~ v3_lo
               v9_lo = v9_lo % 2^32 + vE_lo % 2^32
               v9_hi = v9_hi + vE_hi + floor(v9_lo / 2^32)
               v9_lo = 0|((v9_lo + 2^31) % 2^32 - 2^31)
               v4_lo, v4_hi = v4_lo ~ v9_lo, v4_hi ~ v9_hi
               v4_lo, v4_hi = v4_lo >> 24 | v4_hi << 8, v4_hi >> 24 | v4_lo << 8
               k = row[16] * 2
               v3_lo = v3_lo % 2^32 + v4_lo % 2^32 + W[k-1] % 2^32
               v3_hi = v3_hi + v4_hi + floor(v3_lo / 2^32) + W[k]
               v3_lo = 0|((v3_lo + 2^31) % 2^32 - 2^31)
               vE_lo, vE_hi = vE_lo ~ v3_lo, vE_hi ~ v3_hi
               vE_lo, vE_hi = vE_lo >> 16 | vE_hi << 16, vE_hi >> 16 | vE_lo << 16
               v9_lo = v9_lo % 2^32 + vE_lo % 2^32
               v9_hi = v9_hi + vE_hi + floor(v9_lo / 2^32)
               v9_lo = 0|((v9_lo + 2^31) % 2^32 - 2^31)
               v4_lo, v4_hi = v4_lo ~ v9_lo, v4_hi ~ v9_hi
               v4_lo, v4_hi = v4_lo << 1 | v4_hi >> 31, v4_hi << 1 | v4_lo >> 31
            end
            h1_lo = h1_lo ~ v0_lo ~ v8_lo
            h2_lo = h2_lo ~ v1_lo ~ v9_lo
            h3_lo = h3_lo ~ v2_lo ~ vA_lo
            h4_lo = h4_lo ~ v3_lo ~ vB_lo
            h5_lo = h5_lo ~ v4_lo ~ vC_lo
            h6_lo = h6_lo ~ v5_lo ~ vD_lo
            h7_lo = h7_lo ~ v6_lo ~ vE_lo
            h8_lo = h8_lo ~ v7_lo ~ vF_lo
            h1_hi = h1_hi ~ v0_hi ~ v8_hi
            h2_hi = h2_hi ~ v1_hi ~ v9_hi
            h3_hi = h3_hi ~ v2_hi ~ vA_hi
            h4_hi = h4_hi ~ v3_hi ~ vB_hi
            h5_hi = h5_hi ~ v4_hi ~ vC_hi
            h6_hi = h6_hi ~ v5_hi ~ vD_hi
            h7_hi = h7_hi ~ v6_hi ~ vE_hi
            h8_hi = h8_hi ~ v7_hi ~ vF_hi
         end
         H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
         H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
         return bytes_compressed
      end

      local function blake3_feed_64(str, offs, size, flags, chunk_index, H_in, H_out, wide_output, block_length)
         -- offs >= 0, size >= 0, size is multiple of 64
         block_length = block_length or 64
         local W = common_W
         local h1, h2, h3, h4, h5, h6, h7, h8 = H_in[1], H_in[2], H_in[3], H_in[4], H_in[5], H_in[6], H_in[7], H_in[8]
         H_out = H_out or H_in
         for pos = offs + 1, offs + size, 64 do
            if str then
               W[1], W[2], W[3], W[4], W[5], W[6], W[7], W[8], W[9], W[10], W[11], W[12], W[13], W[14], W[15], W[16] =
                  string_unpack("<i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4i4", str, pos)
            end
            local v0, v1, v2, v3, v4, v5, v6, v7 = h1, h2, h3, h4, h5, h6, h7, h8
            local v8, v9, vA, vB = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4]
            local t0 = chunk_index % 2^32         -- t0 = low_4_bytes(chunk_index)
            local t1 = (chunk_index - t0) / 2^32  -- t1 = high_4_bytes(chunk_index)
            t0 = (t0 + 2^31) % 2^32 - 2^31  -- convert to int32 range (-2^31)..(2^31-1) to avoid "number has no integer representation" error while ORing
            local vC, vD, vE, vF = 0|t0, 0|t1, block_length, flags
            for j = 1, 7 do
               v0 = v0 + v4 + W[perm_blake3[j]]
               vC = vC ~ v0
               vC = vC >> 16 | vC << 16
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = v4 >> 12 | v4 << 20
               v0 = v0 + v4 + W[perm_blake3[j + 14]]
               vC = vC ~ v0
               vC = vC >> 8 | vC << 24
               v8 = v8 + vC
               v4 = v4 ~ v8
               v4 = v4 >> 7 | v4 << 25
               v1 = v1 + v5 + W[perm_blake3[j + 1]]
               vD = vD ~ v1
               vD = vD >> 16 | vD << 16
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = v5 >> 12 | v5 << 20
               v1 = v1 + v5 + W[perm_blake3[j + 2]]
               vD = vD ~ v1
               vD = vD >> 8 | vD << 24
               v9 = v9 + vD
               v5 = v5 ~ v9
               v5 = v5 >> 7 | v5 << 25
               v2 = v2 + v6 + W[perm_blake3[j + 16]]
               vE = vE ~ v2
               vE = vE >> 16 | vE << 16
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = v6 >> 12 | v6 << 20
               v2 = v2 + v6 + W[perm_blake3[j + 7]]
               vE = vE ~ v2
               vE = vE >> 8 | vE << 24
               vA = vA + vE
               v6 = v6 ~ vA
               v6 = v6 >> 7 | v6 << 25
               v3 = v3 + v7 + W[perm_blake3[j + 15]]
               vF = vF ~ v3
               vF = vF >> 16 | vF << 16
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = v7 >> 12 | v7 << 20
               v3 = v3 + v7 + W[perm_blake3[j + 17]]
               vF = vF ~ v3
               vF = vF >> 8 | vF << 24
               vB = vB + vF
               v7 = v7 ~ vB
               v7 = v7 >> 7 | v7 << 25
               v0 = v0 + v5 + W[perm_blake3[j + 21]]
               vF = vF ~ v0
               vF = vF >> 16 | vF << 16
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = v5 >> 12 | v5 << 20
               v0 = v0 + v5 + W[perm_blake3[j + 5]]
               vF = vF ~ v0
               vF = vF >> 8 | vF << 24
               vA = vA + vF
               v5 = v5 ~ vA
               v5 = v5 >> 7 | v5 << 25
               v1 = v1 + v6 + W[perm_blake3[j + 3]]
               vC = vC ~ v1
               vC = vC >> 16 | vC << 16
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = v6 >> 12 | v6 << 20
               v1 = v1 + v6 + W[perm_blake3[j + 6]]
               vC = vC ~ v1
               vC = vC >> 8 | vC << 24
               vB = vB + vC
               v6 = v6 ~ vB
               v6 = v6 >> 7 | v6 << 25
               v2 = v2 + v7 + W[perm_blake3[j + 4]]
               vD = vD ~ v2
               vD = vD >> 16 | vD << 16
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = v7 >> 12 | v7 << 20
               v2 = v2 + v7 + W[perm_blake3[j + 18]]
               vD = vD ~ v2
               vD = vD >> 8 | vD << 24
               v8 = v8 + vD
               v7 = v7 ~ v8
               v7 = v7 >> 7 | v7 << 25
               v3 = v3 + v4 + W[perm_blake3[j + 19]]
               vE = vE ~ v3
               vE = vE >> 16 | vE << 16
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = v4 >> 12 | v4 << 20
               v3 = v3 + v4 + W[perm_blake3[j + 20]]
               vE = vE ~ v3
               vE = vE >> 8 | vE << 24
               v9 = v9 + vE
               v4 = v4 ~ v9
               v4 = v4 >> 7 | v4 << 25
            end
            if wide_output then
               H_out[ 9] = h1 ~ v8
               H_out[10] = h2 ~ v9
               H_out[11] = h3 ~ vA
               H_out[12] = h4 ~ vB
               H_out[13] = h5 ~ vC
               H_out[14] = h6 ~ vD
               H_out[15] = h7 ~ vE
               H_out[16] = h8 ~ vF
            end
            h1 = v0 ~ v8
            h2 = v1 ~ v9
            h3 = v2 ~ vA
            h4 = v3 ~ vB
            h5 = v4 ~ vC
            h6 = v5 ~ vD
            h7 = v6 ~ vE
            h8 = v7 ~ vF
         end
         H_out[1], H_out[2], H_out[3], H_out[4], H_out[5], H_out[6], H_out[7], H_out[8] = h1, h2, h3, h4, h5, h6, h7, h8
      end

      return XORA5, XOR_BYTE, sha256_feed_64, sha512_feed_128, md5_feed_64, sha1_feed_64, keccak_feed, blake2s_feed_64, blake2b_feed_128, blake3_feed_64
   ]=](md5_next_shift, md5_K, sha2_K_lo, sha2_K_hi, build_keccak_format, sha3_RC_lo, sha3_RC_hi, sigma, common_W, sha2_H_lo, sha2_H_hi, perm_blake3)

end

XOR = XOR or XORA5

if branch == "LIB32" or branch == "EMUL" then


	-- implementation for Lua 5.1/5.2 (with or without bitwise library available)

	function sha256_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W, K = common_W, sha2_K_hi
		local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
		for pos = offs, offs + size - 1, 64 do
			for j = 1, 16 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)
				W[j] = ((a * 256 + b) * 256 + c) * 256 + d
			end
			for j = 17, 64 do
				local a, b = W[j-15], W[j-2]
				local a7, a18, b17, b19 = a / 2^7, a / 2^18, b / 2^17, b / 2^19
				W[j] = (XOR(a7 % 1 * (2^32 - 1) + a7, a18 % 1 * (2^32 - 1) + a18, (a - a % 2^3) / 2^3) + W[j-16] + W[j-7]
					+ XOR(b17 % 1 * (2^32 - 1) + b17, b19 % 1 * (2^32 - 1) + b19, (b - b % 2^10) / 2^10)) % 2^32
			end
			local a, b, c, d, e, f, g, h = h1, h2, h3, h4, h5, h6, h7, h8
			for j = 1, 64 do
				e = e % 2^32
				local e6, e11, e7 = e / 2^6, e / 2^11, e * 2^7
				local e7_lo = e7 % 2^32
				local z = AND(e, f) + AND(-1-e, g) + h + K[j] + W[j]
					+ XOR(e6 % 1 * (2^32 - 1) + e6, e11 % 1 * (2^32 - 1) + e11, e7_lo + (e7 - e7_lo) / 2^32)
				h = g
				g = f
				f = e
				e = z + d
				d = c
				c = b
				b = a % 2^32
				local b2, b13, b10 = b / 2^2, b / 2^13, b * 2^10
				local b10_lo = b10 % 2^32
				a = z + AND(d, c) + AND(b, XOR(d, c)) +
					XOR(b2 % 1 * (2^32 - 1) + b2, b13 % 1 * (2^32 - 1) + b13, b10_lo + (b10 - b10_lo) / 2^32)
			end
			h1, h2, h3, h4 = (a + h1) % 2^32, (b + h2) % 2^32, (c + h3) % 2^32, (d + h4) % 2^32
			h5, h6, h7, h8 = (e + h5) % 2^32, (f + h6) % 2^32, (g + h7) % 2^32, (h + h8) % 2^32
		end
		H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
	end


	function sha512_feed_128(H_lo, H_hi, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 128
		-- W1_hi, W1_lo, W2_hi, W2_lo, ...   Wk_hi = W[2*k-1], Wk_lo = W[2*k]
		local W, K_lo, K_hi = common_W, sha2_K_lo, sha2_K_hi
		local h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
		local h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
		for pos = offs, offs + size - 1, 128 do
			for j = 1, 16*2 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)
				W[j] = ((a * 256 + b) * 256 + c) * 256 + d
			end
			for jj = 17*2, 80*2, 2 do
				local a_hi, a_lo, b_hi, b_lo = W[jj-31], W[jj-30], W[jj-5], W[jj-4]
				local b_hi_6, b_hi_19, b_hi_29, b_lo_19, b_lo_29, a_hi_1, a_hi_7, a_hi_8, a_lo_1, a_lo_8 =
					b_hi % 2^6, b_hi % 2^19, b_hi % 2^29, b_lo % 2^19, b_lo % 2^29, a_hi % 2^1, a_hi % 2^7, a_hi % 2^8, a_lo % 2^1, a_lo % 2^8
				local tmp1 = XOR((a_lo - a_lo_1) / 2^1 + a_hi_1 * 2^31, (a_lo - a_lo_8) / 2^8 + a_hi_8 * 2^24, (a_lo - a_lo % 2^7) / 2^7 + a_hi_7 * 2^25) % 2^32
					+ XOR((b_lo - b_lo_19) / 2^19 + b_hi_19 * 2^13, b_lo_29 * 2^3 + (b_hi - b_hi_29) / 2^29, (b_lo - b_lo % 2^6) / 2^6 + b_hi_6 * 2^26) % 2^32
					+ W[jj-14] + W[jj-32]
				local tmp2 = tmp1 % 2^32
				W[jj-1] = (XOR((a_hi - a_hi_1) / 2^1 + a_lo_1 * 2^31, (a_hi - a_hi_8) / 2^8 + a_lo_8 * 2^24, (a_hi - a_hi_7) / 2^7)
					+ XOR((b_hi - b_hi_19) / 2^19 + b_lo_19 * 2^13, b_hi_29 * 2^3 + (b_lo - b_lo_29) / 2^29, (b_hi - b_hi_6) / 2^6)
					+ W[jj-15] + W[jj-33] + (tmp1 - tmp2) / 2^32) % 2^32
				W[jj] = tmp2
			end
			local a_lo, b_lo, c_lo, d_lo, e_lo, f_lo, g_lo, h_lo = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
			local a_hi, b_hi, c_hi, d_hi, e_hi, f_hi, g_hi, h_hi = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
			for j = 1, 80 do
				local jj = 2*j
				local e_lo_9, e_lo_14, e_lo_18, e_hi_9, e_hi_14, e_hi_18 = e_lo % 2^9, e_lo % 2^14, e_lo % 2^18, e_hi % 2^9, e_hi % 2^14, e_hi % 2^18
				local tmp1 = (AND(e_lo, f_lo) + AND(-1-e_lo, g_lo)) % 2^32 + h_lo + K_lo[j] + W[jj]
					+ XOR((e_lo - e_lo_14) / 2^14 + e_hi_14 * 2^18, (e_lo - e_lo_18) / 2^18 + e_hi_18 * 2^14, e_lo_9 * 2^23 + (e_hi - e_hi_9) / 2^9) % 2^32
				local z_lo = tmp1 % 2^32
				local z_hi = AND(e_hi, f_hi) + AND(-1-e_hi, g_hi) + h_hi + K_hi[j] + W[jj-1] + (tmp1 - z_lo) / 2^32
					+ XOR((e_hi - e_hi_14) / 2^14 + e_lo_14 * 2^18, (e_hi - e_hi_18) / 2^18 + e_lo_18 * 2^14, e_hi_9 * 2^23 + (e_lo - e_lo_9) / 2^9)
				h_lo = g_lo;  h_hi = g_hi
				g_lo = f_lo;  g_hi = f_hi
				f_lo = e_lo;  f_hi = e_hi
				tmp1 = z_lo + d_lo
				e_lo = tmp1 % 2^32
				e_hi = (z_hi + d_hi + (tmp1 - e_lo) / 2^32) % 2^32
				d_lo = c_lo;  d_hi = c_hi
				c_lo = b_lo;  c_hi = b_hi
				b_lo = a_lo;  b_hi = a_hi
				local b_lo_2, b_lo_7, b_lo_28, b_hi_2, b_hi_7, b_hi_28 = b_lo % 2^2, b_lo % 2^7, b_lo % 2^28, b_hi % 2^2, b_hi % 2^7, b_hi % 2^28
				tmp1 = z_lo + (AND(d_lo, c_lo) + AND(b_lo, XOR(d_lo, c_lo))) % 2^32
					+ XOR((b_lo - b_lo_28) / 2^28 + b_hi_28 * 2^4, b_lo_2 * 2^30 + (b_hi - b_hi_2) / 2^2, b_lo_7 * 2^25 + (b_hi - b_hi_7) / 2^7) % 2^32
				a_lo = tmp1 % 2^32
				a_hi = (z_hi + AND(d_hi, c_hi) + AND(b_hi, XOR(d_hi, c_hi)) + (tmp1 - a_lo) / 2^32
					+ XOR((b_hi - b_hi_28) / 2^28 + b_lo_28 * 2^4, b_hi_2 * 2^30 + (b_lo - b_lo_2) / 2^2, b_hi_7 * 2^25 + (b_lo - b_lo_7) / 2^7)) % 2^32
			end
			a_lo = h1_lo + a_lo
			h1_lo = a_lo % 2^32
			h1_hi = (h1_hi + a_hi + (a_lo - h1_lo) / 2^32) % 2^32
			a_lo = h2_lo + b_lo
			h2_lo = a_lo % 2^32
			h2_hi = (h2_hi + b_hi + (a_lo - h2_lo) / 2^32) % 2^32
			a_lo = h3_lo + c_lo
			h3_lo = a_lo % 2^32
			h3_hi = (h3_hi + c_hi + (a_lo - h3_lo) / 2^32) % 2^32
			a_lo = h4_lo + d_lo
			h4_lo = a_lo % 2^32
			h4_hi = (h4_hi + d_hi + (a_lo - h4_lo) / 2^32) % 2^32
			a_lo = h5_lo + e_lo
			h5_lo = a_lo % 2^32
			h5_hi = (h5_hi + e_hi + (a_lo - h5_lo) / 2^32) % 2^32
			a_lo = h6_lo + f_lo
			h6_lo = a_lo % 2^32
			h6_hi = (h6_hi + f_hi + (a_lo - h6_lo) / 2^32) % 2^32
			a_lo = h7_lo + g_lo
			h7_lo = a_lo % 2^32
			h7_hi = (h7_hi + g_hi + (a_lo - h7_lo) / 2^32) % 2^32
			a_lo = h8_lo + h_lo
			h8_lo = a_lo % 2^32
			h8_hi = (h8_hi + h_hi + (a_lo - h8_lo) / 2^32) % 2^32
		end
		H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
		H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
	end


	if branch == "LIB32" then

		function md5_feed_64(H, str, offs, size)
			-- offs >= 0, size >= 0, size is multiple of 64
			local W, K, md5_next_shift = common_W, md5_K, md5_next_shift
			local h1, h2, h3, h4 = H[1], H[2], H[3], H[4]
			for pos = offs, offs + size - 1, 64 do
				for j = 1, 16 do
					pos = pos + 4
					local a, b, c, d = byte(str, pos - 3, pos)
					W[j] = ((d * 256 + c) * 256 + b) * 256 + a
				end
				local a, b, c, d = h1, h2, h3, h4
				local s = 25
				for j = 1, 16 do
					local F = ROR(AND(b, c) + AND(-1-b, d) + a + K[j] + W[j], s) + b
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = F
				end
				s = 27
				for j = 17, 32 do
					local F = ROR(AND(d, b) + AND(-1-d, c) + a + K[j] + W[(5*j-4) % 16 + 1], s) + b
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = F
				end
				s = 28
				for j = 33, 48 do
					local F = ROR(XOR(XOR(b, c), d) + a + K[j] + W[(3*j+2) % 16 + 1], s) + b
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = F
				end
				s = 26
				for j = 49, 64 do
					local F = ROR(XOR(c, OR(b, -1-d)) + a + K[j] + W[(j*7-7) % 16 + 1], s) + b
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = F
				end
				h1 = (a + h1) % 2^32
				h2 = (b + h2) % 2^32
				h3 = (c + h3) % 2^32
				h4 = (d + h4) % 2^32
			end
			H[1], H[2], H[3], H[4] = h1, h2, h3, h4
		end

	elseif branch == "EMUL" then

		function md5_feed_64(H, str, offs, size)
			-- offs >= 0, size >= 0, size is multiple of 64
			local W, K, md5_next_shift = common_W, md5_K, md5_next_shift
			local h1, h2, h3, h4 = H[1], H[2], H[3], H[4]
			for pos = offs, offs + size - 1, 64 do
				for j = 1, 16 do
					pos = pos + 4
					local a, b, c, d = byte(str, pos - 3, pos)
					W[j] = ((d * 256 + c) * 256 + b) * 256 + a
				end
				local a, b, c, d = h1, h2, h3, h4
				local s = 25
				for j = 1, 16 do
					local z = (AND(b, c) + AND(-1-b, d) + a + K[j] + W[j]) % 2^32 / 2^s
					local y = z % 1
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = y * 2^32 + (z - y) + b
				end
				s = 27
				for j = 17, 32 do
					local z = (AND(d, b) + AND(-1-d, c) + a + K[j] + W[(5*j-4) % 16 + 1]) % 2^32 / 2^s
					local y = z % 1
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = y * 2^32 + (z - y) + b
				end
				s = 28
				for j = 33, 48 do
					local z = (XOR(XOR(b, c), d) + a + K[j] + W[(3*j+2) % 16 + 1]) % 2^32 / 2^s
					local y = z % 1
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = y * 2^32 + (z - y) + b
				end
				s = 26
				for j = 49, 64 do
					local z = (XOR(c, OR(b, -1-d)) + a + K[j] + W[(j*7-7) % 16 + 1]) % 2^32 / 2^s
					local y = z % 1
					s = md5_next_shift[s]
					a = d
					d = c
					c = b
					b = y * 2^32 + (z - y) + b
				end
				h1 = (a + h1) % 2^32
				h2 = (b + h2) % 2^32
				h3 = (c + h3) % 2^32
				h4 = (d + h4) % 2^32
			end
			H[1], H[2], H[3], H[4] = h1, h2, h3, h4
		end

	end


	function sha1_feed_64(H, str, offs, size)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W = common_W
		local h1, h2, h3, h4, h5 = H[1], H[2], H[3], H[4], H[5]
		for pos = offs, offs + size - 1, 64 do
			for j = 1, 16 do
				pos = pos + 4
				local a, b, c, d = byte(str, pos - 3, pos)
				W[j] = ((a * 256 + b) * 256 + c) * 256 + d
			end
			for j = 17, 80 do
				local a = XOR(W[j-3], W[j-8], W[j-14], W[j-16]) % 2^32 * 2
				local b = a % 2^32
				W[j] = b + (a - b) / 2^32
			end
			local a, b, c, d, e = h1, h2, h3, h4, h5
			for j = 1, 20 do
				local a5 = a * 2^5
				local z = a5 % 2^32
				z = z + (a5 - z) / 2^32 + AND(b, c) + AND(-1-b, d) + 0x5A827999 + W[j] + e        -- constant = floor(2^30 * sqrt(2))
				e = d
				d = c
				c = b / 2^2
				c = c % 1 * (2^32 - 1) + c
				b = a
				a = z % 2^32
			end
			for j = 21, 40 do
				local a5 = a * 2^5
				local z = a5 % 2^32
				z = z + (a5 - z) / 2^32 + XOR(b, c, d) + 0x6ED9EBA1 + W[j] + e                    -- 2^30 * sqrt(3)
				e = d
				d = c
				c = b / 2^2
				c = c % 1 * (2^32 - 1) + c
				b = a
				a = z % 2^32
			end
			for j = 41, 60 do
				local a5 = a * 2^5
				local z = a5 % 2^32
				z = z + (a5 - z) / 2^32 + AND(d, c) + AND(b, XOR(d, c)) + 0x8F1BBCDC + W[j] + e   -- 2^30 * sqrt(5)
				e = d
				d = c
				c = b / 2^2
				c = c % 1 * (2^32 - 1) + c
				b = a
				a = z % 2^32
			end
			for j = 61, 80 do
				local a5 = a * 2^5
				local z = a5 % 2^32
				z = z + (a5 - z) / 2^32 + XOR(b, c, d) + 0xCA62C1D6 + W[j] + e                    -- 2^30 * sqrt(10)
				e = d
				d = c
				c = b / 2^2
				c = c % 1 * (2^32 - 1) + c
				b = a
				a = z % 2^32
			end
			h1 = (a + h1) % 2^32
			h2 = (b + h2) % 2^32
			h3 = (c + h3) % 2^32
			h4 = (d + h4) % 2^32
			h5 = (e + h5) % 2^32
		end
		H[1], H[2], H[3], H[4], H[5] = h1, h2, h3, h4, h5
	end


	function keccak_feed(lanes_lo, lanes_hi, str, offs, size, block_size_in_bytes)
		-- This is an example of a Lua function having 79 local variables :-)
		-- offs >= 0, size >= 0, size is multiple of block_size_in_bytes, block_size_in_bytes is positive multiple of 8
		local RC_lo, RC_hi = sha3_RC_lo, sha3_RC_hi
		local qwords_qty = block_size_in_bytes / 8
		for pos = offs, offs + size - 1, block_size_in_bytes do
			for j = 1, qwords_qty do
				local a, b, c, d = byte(str, pos + 1, pos + 4)
				lanes_lo[j] = XOR(lanes_lo[j], ((d * 256 + c) * 256 + b) * 256 + a)
				pos = pos + 8
				a, b, c, d = byte(str, pos - 3, pos)
				lanes_hi[j] = XOR(lanes_hi[j], ((d * 256 + c) * 256 + b) * 256 + a)
			end
			local L01_lo, L01_hi, L02_lo, L02_hi, L03_lo, L03_hi, L04_lo, L04_hi, L05_lo, L05_hi, L06_lo, L06_hi, L07_lo, L07_hi, L08_lo, L08_hi,
			L09_lo, L09_hi, L10_lo, L10_hi, L11_lo, L11_hi, L12_lo, L12_hi, L13_lo, L13_hi, L14_lo, L14_hi, L15_lo, L15_hi, L16_lo, L16_hi,
			L17_lo, L17_hi, L18_lo, L18_hi, L19_lo, L19_hi, L20_lo, L20_hi, L21_lo, L21_hi, L22_lo, L22_hi, L23_lo, L23_hi, L24_lo, L24_hi, L25_lo, L25_hi =
				lanes_lo[1], lanes_hi[1], lanes_lo[2], lanes_hi[2], lanes_lo[3], lanes_hi[3], lanes_lo[4], lanes_hi[4], lanes_lo[5], lanes_hi[5],
			lanes_lo[6], lanes_hi[6], lanes_lo[7], lanes_hi[7], lanes_lo[8], lanes_hi[8], lanes_lo[9], lanes_hi[9], lanes_lo[10], lanes_hi[10],
			lanes_lo[11], lanes_hi[11], lanes_lo[12], lanes_hi[12], lanes_lo[13], lanes_hi[13], lanes_lo[14], lanes_hi[14], lanes_lo[15], lanes_hi[15],
			lanes_lo[16], lanes_hi[16], lanes_lo[17], lanes_hi[17], lanes_lo[18], lanes_hi[18], lanes_lo[19], lanes_hi[19], lanes_lo[20], lanes_hi[20],
			lanes_lo[21], lanes_hi[21], lanes_lo[22], lanes_hi[22], lanes_lo[23], lanes_hi[23], lanes_lo[24], lanes_hi[24], lanes_lo[25], lanes_hi[25]
			for round_idx = 1, 24 do
				local C1_lo = XOR(L01_lo, L06_lo, L11_lo, L16_lo, L21_lo)
				local C1_hi = XOR(L01_hi, L06_hi, L11_hi, L16_hi, L21_hi)
				local C2_lo = XOR(L02_lo, L07_lo, L12_lo, L17_lo, L22_lo)
				local C2_hi = XOR(L02_hi, L07_hi, L12_hi, L17_hi, L22_hi)
				local C3_lo = XOR(L03_lo, L08_lo, L13_lo, L18_lo, L23_lo)
				local C3_hi = XOR(L03_hi, L08_hi, L13_hi, L18_hi, L23_hi)
				local C4_lo = XOR(L04_lo, L09_lo, L14_lo, L19_lo, L24_lo)
				local C4_hi = XOR(L04_hi, L09_hi, L14_hi, L19_hi, L24_hi)
				local C5_lo = XOR(L05_lo, L10_lo, L15_lo, L20_lo, L25_lo)
				local C5_hi = XOR(L05_hi, L10_hi, L15_hi, L20_hi, L25_hi)
				local D_lo = XOR(C1_lo, C3_lo * 2 + (C3_hi % 2^32 - C3_hi % 2^31) / 2^31)
				local D_hi = XOR(C1_hi, C3_hi * 2 + (C3_lo % 2^32 - C3_lo % 2^31) / 2^31)
				local T0_lo = XOR(D_lo, L02_lo)
				local T0_hi = XOR(D_hi, L02_hi)
				local T1_lo = XOR(D_lo, L07_lo)
				local T1_hi = XOR(D_hi, L07_hi)
				local T2_lo = XOR(D_lo, L12_lo)
				local T2_hi = XOR(D_hi, L12_hi)
				local T3_lo = XOR(D_lo, L17_lo)
				local T3_hi = XOR(D_hi, L17_hi)
				local T4_lo = XOR(D_lo, L22_lo)
				local T4_hi = XOR(D_hi, L22_hi)
				L02_lo = (T1_lo % 2^32 - T1_lo % 2^20) / 2^20 + T1_hi * 2^12
				L02_hi = (T1_hi % 2^32 - T1_hi % 2^20) / 2^20 + T1_lo * 2^12
				L07_lo = (T3_lo % 2^32 - T3_lo % 2^19) / 2^19 + T3_hi * 2^13
				L07_hi = (T3_hi % 2^32 - T3_hi % 2^19) / 2^19 + T3_lo * 2^13
				L12_lo = T0_lo * 2 + (T0_hi % 2^32 - T0_hi % 2^31) / 2^31
				L12_hi = T0_hi * 2 + (T0_lo % 2^32 - T0_lo % 2^31) / 2^31
				L17_lo = T2_lo * 2^10 + (T2_hi % 2^32 - T2_hi % 2^22) / 2^22
				L17_hi = T2_hi * 2^10 + (T2_lo % 2^32 - T2_lo % 2^22) / 2^22
				L22_lo = T4_lo * 2^2 + (T4_hi % 2^32 - T4_hi % 2^30) / 2^30
				L22_hi = T4_hi * 2^2 + (T4_lo % 2^32 - T4_lo % 2^30) / 2^30
				D_lo = XOR(C2_lo, C4_lo * 2 + (C4_hi % 2^32 - C4_hi % 2^31) / 2^31)
				D_hi = XOR(C2_hi, C4_hi * 2 + (C4_lo % 2^32 - C4_lo % 2^31) / 2^31)
				T0_lo = XOR(D_lo, L03_lo)
				T0_hi = XOR(D_hi, L03_hi)
				T1_lo = XOR(D_lo, L08_lo)
				T1_hi = XOR(D_hi, L08_hi)
				T2_lo = XOR(D_lo, L13_lo)
				T2_hi = XOR(D_hi, L13_hi)
				T3_lo = XOR(D_lo, L18_lo)
				T3_hi = XOR(D_hi, L18_hi)
				T4_lo = XOR(D_lo, L23_lo)
				T4_hi = XOR(D_hi, L23_hi)
				L03_lo = (T2_lo % 2^32 - T2_lo % 2^21) / 2^21 + T2_hi * 2^11
				L03_hi = (T2_hi % 2^32 - T2_hi % 2^21) / 2^21 + T2_lo * 2^11
				L08_lo = (T4_lo % 2^32 - T4_lo % 2^3) / 2^3 + T4_hi * 2^29 % 2^32
				L08_hi = (T4_hi % 2^32 - T4_hi % 2^3) / 2^3 + T4_lo * 2^29 % 2^32
				L13_lo = T1_lo * 2^6 + (T1_hi % 2^32 - T1_hi % 2^26) / 2^26
				L13_hi = T1_hi * 2^6 + (T1_lo % 2^32 - T1_lo % 2^26) / 2^26
				L18_lo = T3_lo * 2^15 + (T3_hi % 2^32 - T3_hi % 2^17) / 2^17
				L18_hi = T3_hi * 2^15 + (T3_lo % 2^32 - T3_lo % 2^17) / 2^17
				L23_lo = (T0_lo % 2^32 - T0_lo % 2^2) / 2^2 + T0_hi * 2^30 % 2^32
				L23_hi = (T0_hi % 2^32 - T0_hi % 2^2) / 2^2 + T0_lo * 2^30 % 2^32
				D_lo = XOR(C3_lo, C5_lo * 2 + (C5_hi % 2^32 - C5_hi % 2^31) / 2^31)
				D_hi = XOR(C3_hi, C5_hi * 2 + (C5_lo % 2^32 - C5_lo % 2^31) / 2^31)
				T0_lo = XOR(D_lo, L04_lo)
				T0_hi = XOR(D_hi, L04_hi)
				T1_lo = XOR(D_lo, L09_lo)
				T1_hi = XOR(D_hi, L09_hi)
				T2_lo = XOR(D_lo, L14_lo)
				T2_hi = XOR(D_hi, L14_hi)
				T3_lo = XOR(D_lo, L19_lo)
				T3_hi = XOR(D_hi, L19_hi)
				T4_lo = XOR(D_lo, L24_lo)
				T4_hi = XOR(D_hi, L24_hi)
				L04_lo = T3_lo * 2^21 % 2^32 + (T3_hi % 2^32 - T3_hi % 2^11) / 2^11
				L04_hi = T3_hi * 2^21 % 2^32 + (T3_lo % 2^32 - T3_lo % 2^11) / 2^11
				L09_lo = T0_lo * 2^28 % 2^32 + (T0_hi % 2^32 - T0_hi % 2^4) / 2^4
				L09_hi = T0_hi * 2^28 % 2^32 + (T0_lo % 2^32 - T0_lo % 2^4) / 2^4
				L14_lo = T2_lo * 2^25 % 2^32 + (T2_hi % 2^32 - T2_hi % 2^7) / 2^7
				L14_hi = T2_hi * 2^25 % 2^32 + (T2_lo % 2^32 - T2_lo % 2^7) / 2^7
				L19_lo = (T4_lo % 2^32 - T4_lo % 2^8) / 2^8 + T4_hi * 2^24 % 2^32
				L19_hi = (T4_hi % 2^32 - T4_hi % 2^8) / 2^8 + T4_lo * 2^24 % 2^32
				L24_lo = (T1_lo % 2^32 - T1_lo % 2^9) / 2^9 + T1_hi * 2^23 % 2^32
				L24_hi = (T1_hi % 2^32 - T1_hi % 2^9) / 2^9 + T1_lo * 2^23 % 2^32
				D_lo = XOR(C4_lo, C1_lo * 2 + (C1_hi % 2^32 - C1_hi % 2^31) / 2^31)
				D_hi = XOR(C4_hi, C1_hi * 2 + (C1_lo % 2^32 - C1_lo % 2^31) / 2^31)
				T0_lo = XOR(D_lo, L05_lo)
				T0_hi = XOR(D_hi, L05_hi)
				T1_lo = XOR(D_lo, L10_lo)
				T1_hi = XOR(D_hi, L10_hi)
				T2_lo = XOR(D_lo, L15_lo)
				T2_hi = XOR(D_hi, L15_hi)
				T3_lo = XOR(D_lo, L20_lo)
				T3_hi = XOR(D_hi, L20_hi)
				T4_lo = XOR(D_lo, L25_lo)
				T4_hi = XOR(D_hi, L25_hi)
				L05_lo = T4_lo * 2^14 + (T4_hi % 2^32 - T4_hi % 2^18) / 2^18
				L05_hi = T4_hi * 2^14 + (T4_lo % 2^32 - T4_lo % 2^18) / 2^18
				L10_lo = T1_lo * 2^20 % 2^32 + (T1_hi % 2^32 - T1_hi % 2^12) / 2^12
				L10_hi = T1_hi * 2^20 % 2^32 + (T1_lo % 2^32 - T1_lo % 2^12) / 2^12
				L15_lo = T3_lo * 2^8 + (T3_hi % 2^32 - T3_hi % 2^24) / 2^24
				L15_hi = T3_hi * 2^8 + (T3_lo % 2^32 - T3_lo % 2^24) / 2^24
				L20_lo = T0_lo * 2^27 % 2^32 + (T0_hi % 2^32 - T0_hi % 2^5) / 2^5
				L20_hi = T0_hi * 2^27 % 2^32 + (T0_lo % 2^32 - T0_lo % 2^5) / 2^5
				L25_lo = (T2_lo % 2^32 - T2_lo % 2^25) / 2^25 + T2_hi * 2^7
				L25_hi = (T2_hi % 2^32 - T2_hi % 2^25) / 2^25 + T2_lo * 2^7
				D_lo = XOR(C5_lo, C2_lo * 2 + (C2_hi % 2^32 - C2_hi % 2^31) / 2^31)
				D_hi = XOR(C5_hi, C2_hi * 2 + (C2_lo % 2^32 - C2_lo % 2^31) / 2^31)
				T1_lo = XOR(D_lo, L06_lo)
				T1_hi = XOR(D_hi, L06_hi)
				T2_lo = XOR(D_lo, L11_lo)
				T2_hi = XOR(D_hi, L11_hi)
				T3_lo = XOR(D_lo, L16_lo)
				T3_hi = XOR(D_hi, L16_hi)
				T4_lo = XOR(D_lo, L21_lo)
				T4_hi = XOR(D_hi, L21_hi)
				L06_lo = T2_lo * 2^3 + (T2_hi % 2^32 - T2_hi % 2^29) / 2^29
				L06_hi = T2_hi * 2^3 + (T2_lo % 2^32 - T2_lo % 2^29) / 2^29
				L11_lo = T4_lo * 2^18 + (T4_hi % 2^32 - T4_hi % 2^14) / 2^14
				L11_hi = T4_hi * 2^18 + (T4_lo % 2^32 - T4_lo % 2^14) / 2^14
				L16_lo = (T1_lo % 2^32 - T1_lo % 2^28) / 2^28 + T1_hi * 2^4
				L16_hi = (T1_hi % 2^32 - T1_hi % 2^28) / 2^28 + T1_lo * 2^4
				L21_lo = (T3_lo % 2^32 - T3_lo % 2^23) / 2^23 + T3_hi * 2^9
				L21_hi = (T3_hi % 2^32 - T3_hi % 2^23) / 2^23 + T3_lo * 2^9
				L01_lo = XOR(D_lo, L01_lo)
				L01_hi = XOR(D_hi, L01_hi)
				L01_lo, L02_lo, L03_lo, L04_lo, L05_lo = XOR(L01_lo, AND(-1-L02_lo, L03_lo)), XOR(L02_lo, AND(-1-L03_lo, L04_lo)), XOR(L03_lo, AND(-1-L04_lo, L05_lo)), XOR(L04_lo, AND(-1-L05_lo, L01_lo)), XOR(L05_lo, AND(-1-L01_lo, L02_lo))
				L01_hi, L02_hi, L03_hi, L04_hi, L05_hi = XOR(L01_hi, AND(-1-L02_hi, L03_hi)), XOR(L02_hi, AND(-1-L03_hi, L04_hi)), XOR(L03_hi, AND(-1-L04_hi, L05_hi)), XOR(L04_hi, AND(-1-L05_hi, L01_hi)), XOR(L05_hi, AND(-1-L01_hi, L02_hi))
				L06_lo, L07_lo, L08_lo, L09_lo, L10_lo = XOR(L09_lo, AND(-1-L10_lo, L06_lo)), XOR(L10_lo, AND(-1-L06_lo, L07_lo)), XOR(L06_lo, AND(-1-L07_lo, L08_lo)), XOR(L07_lo, AND(-1-L08_lo, L09_lo)), XOR(L08_lo, AND(-1-L09_lo, L10_lo))
				L06_hi, L07_hi, L08_hi, L09_hi, L10_hi = XOR(L09_hi, AND(-1-L10_hi, L06_hi)), XOR(L10_hi, AND(-1-L06_hi, L07_hi)), XOR(L06_hi, AND(-1-L07_hi, L08_hi)), XOR(L07_hi, AND(-1-L08_hi, L09_hi)), XOR(L08_hi, AND(-1-L09_hi, L10_hi))
				L11_lo, L12_lo, L13_lo, L14_lo, L15_lo = XOR(L12_lo, AND(-1-L13_lo, L14_lo)), XOR(L13_lo, AND(-1-L14_lo, L15_lo)), XOR(L14_lo, AND(-1-L15_lo, L11_lo)), XOR(L15_lo, AND(-1-L11_lo, L12_lo)), XOR(L11_lo, AND(-1-L12_lo, L13_lo))
				L11_hi, L12_hi, L13_hi, L14_hi, L15_hi = XOR(L12_hi, AND(-1-L13_hi, L14_hi)), XOR(L13_hi, AND(-1-L14_hi, L15_hi)), XOR(L14_hi, AND(-1-L15_hi, L11_hi)), XOR(L15_hi, AND(-1-L11_hi, L12_hi)), XOR(L11_hi, AND(-1-L12_hi, L13_hi))
				L16_lo, L17_lo, L18_lo, L19_lo, L20_lo = XOR(L20_lo, AND(-1-L16_lo, L17_lo)), XOR(L16_lo, AND(-1-L17_lo, L18_lo)), XOR(L17_lo, AND(-1-L18_lo, L19_lo)), XOR(L18_lo, AND(-1-L19_lo, L20_lo)), XOR(L19_lo, AND(-1-L20_lo, L16_lo))
				L16_hi, L17_hi, L18_hi, L19_hi, L20_hi = XOR(L20_hi, AND(-1-L16_hi, L17_hi)), XOR(L16_hi, AND(-1-L17_hi, L18_hi)), XOR(L17_hi, AND(-1-L18_hi, L19_hi)), XOR(L18_hi, AND(-1-L19_hi, L20_hi)), XOR(L19_hi, AND(-1-L20_hi, L16_hi))
				L21_lo, L22_lo, L23_lo, L24_lo, L25_lo = XOR(L23_lo, AND(-1-L24_lo, L25_lo)), XOR(L24_lo, AND(-1-L25_lo, L21_lo)), XOR(L25_lo, AND(-1-L21_lo, L22_lo)), XOR(L21_lo, AND(-1-L22_lo, L23_lo)), XOR(L22_lo, AND(-1-L23_lo, L24_lo))
				L21_hi, L22_hi, L23_hi, L24_hi, L25_hi = XOR(L23_hi, AND(-1-L24_hi, L25_hi)), XOR(L24_hi, AND(-1-L25_hi, L21_hi)), XOR(L25_hi, AND(-1-L21_hi, L22_hi)), XOR(L21_hi, AND(-1-L22_hi, L23_hi)), XOR(L22_hi, AND(-1-L23_hi, L24_hi))
				L01_lo = XOR(L01_lo, RC_lo[round_idx])
				L01_hi = L01_hi + RC_hi[round_idx]      -- RC_hi[] is either 0 or 0x80000000, so we could use fast addition instead of slow XOR
			end
			lanes_lo[1]  = L01_lo;  lanes_hi[1]  = L01_hi
			lanes_lo[2]  = L02_lo;  lanes_hi[2]  = L02_hi
			lanes_lo[3]  = L03_lo;  lanes_hi[3]  = L03_hi
			lanes_lo[4]  = L04_lo;  lanes_hi[4]  = L04_hi
			lanes_lo[5]  = L05_lo;  lanes_hi[5]  = L05_hi
			lanes_lo[6]  = L06_lo;  lanes_hi[6]  = L06_hi
			lanes_lo[7]  = L07_lo;  lanes_hi[7]  = L07_hi
			lanes_lo[8]  = L08_lo;  lanes_hi[8]  = L08_hi
			lanes_lo[9]  = L09_lo;  lanes_hi[9]  = L09_hi
			lanes_lo[10] = L10_lo;  lanes_hi[10] = L10_hi
			lanes_lo[11] = L11_lo;  lanes_hi[11] = L11_hi
			lanes_lo[12] = L12_lo;  lanes_hi[12] = L12_hi
			lanes_lo[13] = L13_lo;  lanes_hi[13] = L13_hi
			lanes_lo[14] = L14_lo;  lanes_hi[14] = L14_hi
			lanes_lo[15] = L15_lo;  lanes_hi[15] = L15_hi
			lanes_lo[16] = L16_lo;  lanes_hi[16] = L16_hi
			lanes_lo[17] = L17_lo;  lanes_hi[17] = L17_hi
			lanes_lo[18] = L18_lo;  lanes_hi[18] = L18_hi
			lanes_lo[19] = L19_lo;  lanes_hi[19] = L19_hi
			lanes_lo[20] = L20_lo;  lanes_hi[20] = L20_hi
			lanes_lo[21] = L21_lo;  lanes_hi[21] = L21_hi
			lanes_lo[22] = L22_lo;  lanes_hi[22] = L22_hi
			lanes_lo[23] = L23_lo;  lanes_hi[23] = L23_hi
			lanes_lo[24] = L24_lo;  lanes_hi[24] = L24_hi
			lanes_lo[25] = L25_lo;  lanes_hi[25] = L25_hi
		end
	end


	function blake2s_feed_64(H, str, offs, size, bytes_compressed, last_block_size, is_last_node)
		-- offs >= 0, size >= 0, size is multiple of 64
		local W = common_W
		local h1, h2, h3, h4, h5, h6, h7, h8 = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
		for pos = offs, offs + size - 1, 64 do
			if str then
				for j = 1, 16 do
					pos = pos + 4
					local a, b, c, d = byte(str, pos - 3, pos)
					W[j] = ((d * 256 + c) * 256 + b) * 256 + a
				end
			end
			local v0, v1, v2, v3, v4, v5, v6, v7 = h1, h2, h3, h4, h5, h6, h7, h8
			local v8, v9, vA, vB, vC, vD, vE, vF = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4], sha2_H_hi[5], sha2_H_hi[6], sha2_H_hi[7], sha2_H_hi[8]
			bytes_compressed = bytes_compressed + (last_block_size or 64)
			local t0 = bytes_compressed % 2^32
			local t1 = (bytes_compressed - t0) / 2^32
			vC = XOR(vC, t0)  -- t0 = low_4_bytes(bytes_compressed)
			vD = XOR(vD, t1)  -- t1 = high_4_bytes(bytes_compressed)
			if last_block_size then  -- flag f0
				vE = -1 - vE
			end
			if is_last_node then  -- flag f1
				vF = -1 - vF
			end
			for j = 1, 10 do
				local row = sigma[j]
				v0 = v0 + v4 + W[row[1]]
				vC = XOR(vC, v0) % 2^32 / 2^16
				vC = vC % 1 * (2^32 - 1) + vC
				v8 = v8 + vC
				v4 = XOR(v4, v8) % 2^32 / 2^12
				v4 = v4 % 1 * (2^32 - 1) + v4
				v0 = v0 + v4 + W[row[2]]
				vC = XOR(vC, v0) % 2^32 / 2^8
				vC = vC % 1 * (2^32 - 1) + vC
				v8 = v8 + vC
				v4 = XOR(v4, v8) % 2^32 / 2^7
				v4 = v4 % 1 * (2^32 - 1) + v4
				v1 = v1 + v5 + W[row[3]]
				vD = XOR(vD, v1) % 2^32 / 2^16
				vD = vD % 1 * (2^32 - 1) + vD
				v9 = v9 + vD
				v5 = XOR(v5, v9) % 2^32 / 2^12
				v5 = v5 % 1 * (2^32 - 1) + v5
				v1 = v1 + v5 + W[row[4]]
				vD = XOR(vD, v1) % 2^32 / 2^8
				vD = vD % 1 * (2^32 - 1) + vD
				v9 = v9 + vD
				v5 = XOR(v5, v9) % 2^32 / 2^7
				v5 = v5 % 1 * (2^32 - 1) + v5
				v2 = v2 + v6 + W[row[5]]
				vE = XOR(vE, v2) % 2^32 / 2^16
				vE = vE % 1 * (2^32 - 1) + vE
				vA = vA + vE
				v6 = XOR(v6, vA) % 2^32 / 2^12
				v6 = v6 % 1 * (2^32 - 1) + v6
				v2 = v2 + v6 + W[row[6]]
				vE = XOR(vE, v2) % 2^32 / 2^8
				vE = vE % 1 * (2^32 - 1) + vE
				vA = vA + vE
				v6 = XOR(v6, vA) % 2^32 / 2^7
				v6 = v6 % 1 * (2^32 - 1) + v6
				v3 = v3 + v7 + W[row[7]]
				vF = XOR(vF, v3) % 2^32 / 2^16
				vF = vF % 1 * (2^32 - 1) + vF
				vB = vB + vF
				v7 = XOR(v7, vB) % 2^32 / 2^12
				v7 = v7 % 1 * (2^32 - 1) + v7
				v3 = v3 + v7 + W[row[8]]
				vF = XOR(vF, v3) % 2^32 / 2^8
				vF = vF % 1 * (2^32 - 1) + vF
				vB = vB + vF
				v7 = XOR(v7, vB) % 2^32 / 2^7
				v7 = v7 % 1 * (2^32 - 1) + v7
				v0 = v0 + v5 + W[row[9]]
				vF = XOR(vF, v0) % 2^32 / 2^16
				vF = vF % 1 * (2^32 - 1) + vF
				vA = vA + vF
				v5 = XOR(v5, vA) % 2^32 / 2^12
				v5 = v5 % 1 * (2^32 - 1) + v5
				v0 = v0 + v5 + W[row[10]]
				vF = XOR(vF, v0) % 2^32 / 2^8
				vF = vF % 1 * (2^32 - 1) + vF
				vA = vA + vF
				v5 = XOR(v5, vA) % 2^32 / 2^7
				v5 = v5 % 1 * (2^32 - 1) + v5
				v1 = v1 + v6 + W[row[11]]
				vC = XOR(vC, v1) % 2^32 / 2^16
				vC = vC % 1 * (2^32 - 1) + vC
				vB = vB + vC
				v6 = XOR(v6, vB) % 2^32 / 2^12
				v6 = v6 % 1 * (2^32 - 1) + v6
				v1 = v1 + v6 + W[row[12]]
				vC = XOR(vC, v1) % 2^32 / 2^8
				vC = vC % 1 * (2^32 - 1) + vC
				vB = vB + vC
				v6 = XOR(v6, vB) % 2^32 / 2^7
				v6 = v6 % 1 * (2^32 - 1) + v6
				v2 = v2 + v7 + W[row[13]]
				vD = XOR(vD, v2) % 2^32 / 2^16
				vD = vD % 1 * (2^32 - 1) + vD
				v8 = v8 + vD
				v7 = XOR(v7, v8) % 2^32 / 2^12
				v7 = v7 % 1 * (2^32 - 1) + v7
				v2 = v2 + v7 + W[row[14]]
				vD = XOR(vD, v2) % 2^32 / 2^8
				vD = vD % 1 * (2^32 - 1) + vD
				v8 = v8 + vD
				v7 = XOR(v7, v8) % 2^32 / 2^7
				v7 = v7 % 1 * (2^32 - 1) + v7
				v3 = v3 + v4 + W[row[15]]
				vE = XOR(vE, v3) % 2^32 / 2^16
				vE = vE % 1 * (2^32 - 1) + vE
				v9 = v9 + vE
				v4 = XOR(v4, v9) % 2^32 / 2^12
				v4 = v4 % 1 * (2^32 - 1) + v4
				v3 = v3 + v4 + W[row[16]]
				vE = XOR(vE, v3) % 2^32 / 2^8
				vE = vE % 1 * (2^32 - 1) + vE
				v9 = v9 + vE
				v4 = XOR(v4, v9) % 2^32 / 2^7
				v4 = v4 % 1 * (2^32 - 1) + v4
			end
			h1 = XOR(h1, v0, v8)
			h2 = XOR(h2, v1, v9)
			h3 = XOR(h3, v2, vA)
			h4 = XOR(h4, v3, vB)
			h5 = XOR(h5, v4, vC)
			h6 = XOR(h6, v5, vD)
			h7 = XOR(h7, v6, vE)
			h8 = XOR(h8, v7, vF)
		end
		H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] = h1, h2, h3, h4, h5, h6, h7, h8
		return bytes_compressed
	end


	function blake2b_feed_128(H_lo, H_hi, str, offs, size, bytes_compressed, last_block_size, is_last_node)
		-- offs >= 0, size >= 0, size is multiple of 128
		local W = common_W
		local h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo = H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8]
		local h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi = H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8]
		for pos = offs, offs + size - 1, 128 do
			if str then
				for j = 1, 32 do
					pos = pos + 4
					local a, b, c, d = byte(str, pos - 3, pos)
					W[j] = ((d * 256 + c) * 256 + b) * 256 + a
				end
			end
			local v0_lo, v1_lo, v2_lo, v3_lo, v4_lo, v5_lo, v6_lo, v7_lo = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
			local v0_hi, v1_hi, v2_hi, v3_hi, v4_hi, v5_hi, v6_hi, v7_hi = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
			local v8_lo, v9_lo, vA_lo, vB_lo, vC_lo, vD_lo, vE_lo, vF_lo = sha2_H_lo[1], sha2_H_lo[2], sha2_H_lo[3], sha2_H_lo[4], sha2_H_lo[5], sha2_H_lo[6], sha2_H_lo[7], sha2_H_lo[8]
			local v8_hi, v9_hi, vA_hi, vB_hi, vC_hi, vD_hi, vE_hi, vF_hi = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4], sha2_H_hi[5], sha2_H_hi[6], sha2_H_hi[7], sha2_H_hi[8]
			bytes_compressed = bytes_compressed + (last_block_size or 128)
			local t0_lo = bytes_compressed % 2^32
			local t0_hi = (bytes_compressed - t0_lo) / 2^32
			vC_lo = XOR(vC_lo, t0_lo)  -- t0 = low_8_bytes(bytes_compressed)
			vC_hi = XOR(vC_hi, t0_hi)
			-- t1 = high_8_bytes(bytes_compressed) = 0,  message length is always below 2^53 bytes
			if last_block_size then  -- flag f0
				vE_lo = -1 - vE_lo
				vE_hi = -1 - vE_hi
			end
			if is_last_node then  -- flag f1
				vF_lo = -1 - vF_lo
				vF_hi = -1 - vF_hi
			end
			for j = 1, 12 do
				local row = sigma[j]
				local k = row[1] * 2
				local z = v0_lo % 2^32 + v4_lo % 2^32 + W[k-1]
				v0_lo = z % 2^32
				v0_hi = v0_hi + v4_hi + (z - v0_lo) / 2^32 + W[k]
				vC_lo, vC_hi = XOR(vC_hi, v0_hi), XOR(vC_lo, v0_lo)
				z = v8_lo % 2^32 + vC_lo % 2^32
				v8_lo = z % 2^32
				v8_hi = v8_hi + vC_hi + (z - v8_lo) / 2^32
				v4_lo, v4_hi = XOR(v4_lo, v8_lo), XOR(v4_hi, v8_hi)
				local z_lo, z_hi = v4_lo % 2^24, v4_hi % 2^24
				v4_lo, v4_hi = (v4_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v4_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[2] * 2
				z = v0_lo % 2^32 + v4_lo % 2^32 + W[k-1]
				v0_lo = z % 2^32
				v0_hi = v0_hi + v4_hi + (z - v0_lo) / 2^32 + W[k]
				vC_lo, vC_hi = XOR(vC_lo, v0_lo), XOR(vC_hi, v0_hi)
				z_lo, z_hi = vC_lo % 2^16, vC_hi % 2^16
				vC_lo, vC_hi = (vC_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vC_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = v8_lo % 2^32 + vC_lo % 2^32
				v8_lo = z % 2^32
				v8_hi = v8_hi + vC_hi + (z - v8_lo) / 2^32
				v4_lo, v4_hi = XOR(v4_lo, v8_lo), XOR(v4_hi, v8_hi)
				z_lo, z_hi = v4_lo % 2^31, v4_hi % 2^31
				v4_lo, v4_hi = z_lo * 2^1 + (v4_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v4_lo - z_lo) / 2^31 % 2^1
				k = row[3] * 2
				z = v1_lo % 2^32 + v5_lo % 2^32 + W[k-1]
				v1_lo = z % 2^32
				v1_hi = v1_hi + v5_hi + (z - v1_lo) / 2^32 + W[k]
				vD_lo, vD_hi = XOR(vD_hi, v1_hi), XOR(vD_lo, v1_lo)
				z = v9_lo % 2^32 + vD_lo % 2^32
				v9_lo = z % 2^32
				v9_hi = v9_hi + vD_hi + (z - v9_lo) / 2^32
				v5_lo, v5_hi = XOR(v5_lo, v9_lo), XOR(v5_hi, v9_hi)
				z_lo, z_hi = v5_lo % 2^24, v5_hi % 2^24
				v5_lo, v5_hi = (v5_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v5_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[4] * 2
				z = v1_lo % 2^32 + v5_lo % 2^32 + W[k-1]
				v1_lo = z % 2^32
				v1_hi = v1_hi + v5_hi + (z - v1_lo) / 2^32 + W[k]
				vD_lo, vD_hi = XOR(vD_lo, v1_lo), XOR(vD_hi, v1_hi)
				z_lo, z_hi = vD_lo % 2^16, vD_hi % 2^16
				vD_lo, vD_hi = (vD_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vD_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = v9_lo % 2^32 + vD_lo % 2^32
				v9_lo = z % 2^32
				v9_hi = v9_hi + vD_hi + (z - v9_lo) / 2^32
				v5_lo, v5_hi = XOR(v5_lo, v9_lo), XOR(v5_hi, v9_hi)
				z_lo, z_hi = v5_lo % 2^31, v5_hi % 2^31
				v5_lo, v5_hi = z_lo * 2^1 + (v5_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v5_lo - z_lo) / 2^31 % 2^1
				k = row[5] * 2
				z = v2_lo % 2^32 + v6_lo % 2^32 + W[k-1]
				v2_lo = z % 2^32
				v2_hi = v2_hi + v6_hi + (z - v2_lo) / 2^32 + W[k]
				vE_lo, vE_hi = XOR(vE_hi, v2_hi), XOR(vE_lo, v2_lo)
				z = vA_lo % 2^32 + vE_lo % 2^32
				vA_lo = z % 2^32
				vA_hi = vA_hi + vE_hi + (z - vA_lo) / 2^32
				v6_lo, v6_hi = XOR(v6_lo, vA_lo), XOR(v6_hi, vA_hi)
				z_lo, z_hi = v6_lo % 2^24, v6_hi % 2^24
				v6_lo, v6_hi = (v6_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v6_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[6] * 2
				z = v2_lo % 2^32 + v6_lo % 2^32 + W[k-1]
				v2_lo = z % 2^32
				v2_hi = v2_hi + v6_hi + (z - v2_lo) / 2^32 + W[k]
				vE_lo, vE_hi = XOR(vE_lo, v2_lo), XOR(vE_hi, v2_hi)
				z_lo, z_hi = vE_lo % 2^16, vE_hi % 2^16
				vE_lo, vE_hi = (vE_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vE_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = vA_lo % 2^32 + vE_lo % 2^32
				vA_lo = z % 2^32
				vA_hi = vA_hi + vE_hi + (z - vA_lo) / 2^32
				v6_lo, v6_hi = XOR(v6_lo, vA_lo), XOR(v6_hi, vA_hi)
				z_lo, z_hi = v6_lo % 2^31, v6_hi % 2^31
				v6_lo, v6_hi = z_lo * 2^1 + (v6_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v6_lo - z_lo) / 2^31 % 2^1
				k = row[7] * 2
				z = v3_lo % 2^32 + v7_lo % 2^32 + W[k-1]
				v3_lo = z % 2^32
				v3_hi = v3_hi + v7_hi + (z - v3_lo) / 2^32 + W[k]
				vF_lo, vF_hi = XOR(vF_hi, v3_hi), XOR(vF_lo, v3_lo)
				z = vB_lo % 2^32 + vF_lo % 2^32
				vB_lo = z % 2^32
				vB_hi = vB_hi + vF_hi + (z - vB_lo) / 2^32
				v7_lo, v7_hi = XOR(v7_lo, vB_lo), XOR(v7_hi, vB_hi)
				z_lo, z_hi = v7_lo % 2^24, v7_hi % 2^24
				v7_lo, v7_hi = (v7_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v7_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[8] * 2
				z = v3_lo % 2^32 + v7_lo % 2^32 + W[k-1]
				v3_lo = z % 2^32
				v3_hi = v3_hi + v7_hi + (z - v3_lo) / 2^32 + W[k]
				vF_lo, vF_hi = XOR(vF_lo, v3_lo), XOR(vF_hi, v3_hi)
				z_lo, z_hi = vF_lo % 2^16, vF_hi % 2^16
				vF_lo, vF_hi = (vF_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vF_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = vB_lo % 2^32 + vF_lo % 2^32
				vB_lo = z % 2^32
				vB_hi = vB_hi + vF_hi + (z - vB_lo) / 2^32
				v7_lo, v7_hi = XOR(v7_lo, vB_lo), XOR(v7_hi, vB_hi)
				z_lo, z_hi = v7_lo % 2^31, v7_hi % 2^31
				v7_lo, v7_hi = z_lo * 2^1 + (v7_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v7_lo - z_lo) / 2^31 % 2^1
				k = row[9] * 2
				z = v0_lo % 2^32 + v5_lo % 2^32 + W[k-1]
				v0_lo = z % 2^32
				v0_hi = v0_hi + v5_hi + (z - v0_lo) / 2^32 + W[k]
				vF_lo, vF_hi = XOR(vF_hi, v0_hi), XOR(vF_lo, v0_lo)
				z = vA_lo % 2^32 + vF_lo % 2^32
				vA_lo = z % 2^32
				vA_hi = vA_hi + vF_hi + (z - vA_lo) / 2^32
				v5_lo, v5_hi = XOR(v5_lo, vA_lo), XOR(v5_hi, vA_hi)
				z_lo, z_hi = v5_lo % 2^24, v5_hi % 2^24
				v5_lo, v5_hi = (v5_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v5_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[10] * 2
				z = v0_lo % 2^32 + v5_lo % 2^32 + W[k-1]
				v0_lo = z % 2^32
				v0_hi = v0_hi + v5_hi + (z - v0_lo) / 2^32 + W[k]
				vF_lo, vF_hi = XOR(vF_lo, v0_lo), XOR(vF_hi, v0_hi)
				z_lo, z_hi = vF_lo % 2^16, vF_hi % 2^16
				vF_lo, vF_hi = (vF_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vF_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = vA_lo % 2^32 + vF_lo % 2^32
				vA_lo = z % 2^32
				vA_hi = vA_hi + vF_hi + (z - vA_lo) / 2^32
				v5_lo, v5_hi = XOR(v5_lo, vA_lo), XOR(v5_hi, vA_hi)
				z_lo, z_hi = v5_lo % 2^31, v5_hi % 2^31
				v5_lo, v5_hi = z_lo * 2^1 + (v5_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v5_lo - z_lo) / 2^31 % 2^1
				k = row[11] * 2
				z = v1_lo % 2^32 + v6_lo % 2^32 + W[k-1]
				v1_lo = z % 2^32
				v1_hi = v1_hi + v6_hi + (z - v1_lo) / 2^32 + W[k]
				vC_lo, vC_hi = XOR(vC_hi, v1_hi), XOR(vC_lo, v1_lo)
				z = vB_lo % 2^32 + vC_lo % 2^32
				vB_lo = z % 2^32
				vB_hi = vB_hi + vC_hi + (z - vB_lo) / 2^32
				v6_lo, v6_hi = XOR(v6_lo, vB_lo), XOR(v6_hi, vB_hi)
				z_lo, z_hi = v6_lo % 2^24, v6_hi % 2^24
				v6_lo, v6_hi = (v6_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v6_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[12] * 2
				z = v1_lo % 2^32 + v6_lo % 2^32 + W[k-1]
				v1_lo = z % 2^32
				v1_hi = v1_hi + v6_hi + (z - v1_lo) / 2^32 + W[k]
				vC_lo, vC_hi = XOR(vC_lo, v1_lo), XOR(vC_hi, v1_hi)
				z_lo, z_hi = vC_lo % 2^16, vC_hi % 2^16
				vC_lo, vC_hi = (vC_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vC_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = vB_lo % 2^32 + vC_lo % 2^32
				vB_lo = z % 2^32
				vB_hi = vB_hi + vC_hi + (z - vB_lo) / 2^32
				v6_lo, v6_hi = XOR(v6_lo, vB_lo), XOR(v6_hi, vB_hi)
				z_lo, z_hi = v6_lo % 2^31, v6_hi % 2^31
				v6_lo, v6_hi = z_lo * 2^1 + (v6_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v6_lo - z_lo) / 2^31 % 2^1
				k = row[13] * 2
				z = v2_lo % 2^32 + v7_lo % 2^32 + W[k-1]
				v2_lo = z % 2^32
				v2_hi = v2_hi + v7_hi + (z - v2_lo) / 2^32 + W[k]
				vD_lo, vD_hi = XOR(vD_hi, v2_hi), XOR(vD_lo, v2_lo)
				z = v8_lo % 2^32 + vD_lo % 2^32
				v8_lo = z % 2^32
				v8_hi = v8_hi + vD_hi + (z - v8_lo) / 2^32
				v7_lo, v7_hi = XOR(v7_lo, v8_lo), XOR(v7_hi, v8_hi)
				z_lo, z_hi = v7_lo % 2^24, v7_hi % 2^24
				v7_lo, v7_hi = (v7_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v7_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[14] * 2
				z = v2_lo % 2^32 + v7_lo % 2^32 + W[k-1]
				v2_lo = z % 2^32
				v2_hi = v2_hi + v7_hi + (z - v2_lo) / 2^32 + W[k]
				vD_lo, vD_hi = XOR(vD_lo, v2_lo), XOR(vD_hi, v2_hi)
				z_lo, z_hi = vD_lo % 2^16, vD_hi % 2^16
				vD_lo, vD_hi = (vD_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vD_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = v8_lo % 2^32 + vD_lo % 2^32
				v8_lo = z % 2^32
				v8_hi = v8_hi + vD_hi + (z - v8_lo) / 2^32
				v7_lo, v7_hi = XOR(v7_lo, v8_lo), XOR(v7_hi, v8_hi)
				z_lo, z_hi = v7_lo % 2^31, v7_hi % 2^31
				v7_lo, v7_hi = z_lo * 2^1 + (v7_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v7_lo - z_lo) / 2^31 % 2^1
				k = row[15] * 2
				z = v3_lo % 2^32 + v4_lo % 2^32 + W[k-1]
				v3_lo = z % 2^32
				v3_hi = v3_hi + v4_hi + (z - v3_lo) / 2^32 + W[k]
				vE_lo, vE_hi = XOR(vE_hi, v3_hi), XOR(vE_lo, v3_lo)
				z = v9_lo % 2^32 + vE_lo % 2^32
				v9_lo = z % 2^32
				v9_hi = v9_hi + vE_hi + (z - v9_lo) / 2^32
				v4_lo, v4_hi = XOR(v4_lo, v9_lo), XOR(v4_hi, v9_hi)
				z_lo, z_hi = v4_lo % 2^24, v4_hi % 2^24
				v4_lo, v4_hi = (v4_lo - z_lo) / 2^24 % 2^8 + z_hi * 2^8, (v4_hi - z_hi) / 2^24 % 2^8 + z_lo * 2^8
				k = row[16] * 2
				z = v3_lo % 2^32 + v4_lo % 2^32 + W[k-1]
				v3_lo = z % 2^32
				v3_hi = v3_hi + v4_hi + (z - v3_lo) / 2^32 + W[k]
				vE_lo, vE_hi = XOR(vE_lo, v3_lo), XOR(vE_hi, v3_hi)
				z_lo, z_hi = vE_lo % 2^16, vE_hi % 2^16
				vE_lo, vE_hi = (vE_lo - z_lo) / 2^16 % 2^16 + z_hi * 2^16, (vE_hi - z_hi) / 2^16 % 2^16 + z_lo * 2^16
				z = v9_lo % 2^32 + vE_lo % 2^32
				v9_lo = z % 2^32
				v9_hi = v9_hi + vE_hi + (z - v9_lo) / 2^32
				v4_lo, v4_hi = XOR(v4_lo, v9_lo), XOR(v4_hi, v9_hi)
				z_lo, z_hi = v4_lo % 2^31, v4_hi % 2^31
				v4_lo, v4_hi = z_lo * 2^1 + (v4_hi - z_hi) / 2^31 % 2^1, z_hi * 2^1 + (v4_lo - z_lo) / 2^31 % 2^1
			end
			h1_lo = XOR(h1_lo, v0_lo, v8_lo) % 2^32
			h2_lo = XOR(h2_lo, v1_lo, v9_lo) % 2^32
			h3_lo = XOR(h3_lo, v2_lo, vA_lo) % 2^32
			h4_lo = XOR(h4_lo, v3_lo, vB_lo) % 2^32
			h5_lo = XOR(h5_lo, v4_lo, vC_lo) % 2^32
			h6_lo = XOR(h6_lo, v5_lo, vD_lo) % 2^32
			h7_lo = XOR(h7_lo, v6_lo, vE_lo) % 2^32
			h8_lo = XOR(h8_lo, v7_lo, vF_lo) % 2^32
			h1_hi = XOR(h1_hi, v0_hi, v8_hi) % 2^32
			h2_hi = XOR(h2_hi, v1_hi, v9_hi) % 2^32
			h3_hi = XOR(h3_hi, v2_hi, vA_hi) % 2^32
			h4_hi = XOR(h4_hi, v3_hi, vB_hi) % 2^32
			h5_hi = XOR(h5_hi, v4_hi, vC_hi) % 2^32
			h6_hi = XOR(h6_hi, v5_hi, vD_hi) % 2^32
			h7_hi = XOR(h7_hi, v6_hi, vE_hi) % 2^32
			h8_hi = XOR(h8_hi, v7_hi, vF_hi) % 2^32
		end
		H_lo[1], H_lo[2], H_lo[3], H_lo[4], H_lo[5], H_lo[6], H_lo[7], H_lo[8] = h1_lo, h2_lo, h3_lo, h4_lo, h5_lo, h6_lo, h7_lo, h8_lo
		H_hi[1], H_hi[2], H_hi[3], H_hi[4], H_hi[5], H_hi[6], H_hi[7], H_hi[8] = h1_hi, h2_hi, h3_hi, h4_hi, h5_hi, h6_hi, h7_hi, h8_hi
		return bytes_compressed
	end


	function blake3_feed_64(str, offs, size, flags, chunk_index, H_in, H_out, wide_output, block_length)
		-- offs >= 0, size >= 0, size is multiple of 64
		block_length = block_length or 64
		local W = common_W
		local h1, h2, h3, h4, h5, h6, h7, h8 = H_in[1], H_in[2], H_in[3], H_in[4], H_in[5], H_in[6], H_in[7], H_in[8]
		H_out = H_out or H_in
		for pos = offs, offs + size - 1, 64 do
			if str then
				for j = 1, 16 do
					pos = pos + 4
					local a, b, c, d = byte(str, pos - 3, pos)
					W[j] = ((d * 256 + c) * 256 + b) * 256 + a
				end
			end
			local v0, v1, v2, v3, v4, v5, v6, v7 = h1, h2, h3, h4, h5, h6, h7, h8
			local v8, v9, vA, vB = sha2_H_hi[1], sha2_H_hi[2], sha2_H_hi[3], sha2_H_hi[4]
			local vC = chunk_index % 2^32         -- t0 = low_4_bytes(chunk_index)
			local vD = (chunk_index - vC) / 2^32  -- t1 = high_4_bytes(chunk_index)
			local vE, vF = block_length, flags
			for j = 1, 7 do
				v0 = v0 + v4 + W[perm_blake3[j]]
				vC = XOR(vC, v0) % 2^32 / 2^16
				vC = vC % 1 * (2^32 - 1) + vC
				v8 = v8 + vC
				v4 = XOR(v4, v8) % 2^32 / 2^12
				v4 = v4 % 1 * (2^32 - 1) + v4
				v0 = v0 + v4 + W[perm_blake3[j + 14]]
				vC = XOR(vC, v0) % 2^32 / 2^8
				vC = vC % 1 * (2^32 - 1) + vC
				v8 = v8 + vC
				v4 = XOR(v4, v8) % 2^32 / 2^7
				v4 = v4 % 1 * (2^32 - 1) + v4
				v1 = v1 + v5 + W[perm_blake3[j + 1]]
				vD = XOR(vD, v1) % 2^32 / 2^16
				vD = vD % 1 * (2^32 - 1) + vD
				v9 = v9 + vD
				v5 = XOR(v5, v9) % 2^32 / 2^12
				v5 = v5 % 1 * (2^32 - 1) + v5
				v1 = v1 + v5 + W[perm_blake3[j + 2]]
				vD = XOR(vD, v1) % 2^32 / 2^8
				vD = vD % 1 * (2^32 - 1) + vD
				v9 = v9 + vD
				v5 = XOR(v5, v9) % 2^32 / 2^7
				v5 = v5 % 1 * (2^32 - 1) + v5
				v2 = v2 + v6 + W[perm_blake3[j + 16]]
				vE = XOR(vE, v2) % 2^32 / 2^16
				vE = vE % 1 * (2^32 - 1) + vE
				vA = vA + vE
				v6 = XOR(v6, vA) % 2^32 / 2^12
				v6 = v6 % 1 * (2^32 - 1) + v6
				v2 = v2 + v6 + W[perm_blake3[j + 7]]
				vE = XOR(vE, v2) % 2^32 / 2^8
				vE = vE % 1 * (2^32 - 1) + vE
				vA = vA + vE
				v6 = XOR(v6, vA) % 2^32 / 2^7
				v6 = v6 % 1 * (2^32 - 1) + v6
				v3 = v3 + v7 + W[perm_blake3[j + 15]]
				vF = XOR(vF, v3) % 2^32 / 2^16
				vF = vF % 1 * (2^32 - 1) + vF
				vB = vB + vF
				v7 = XOR(v7, vB) % 2^32 / 2^12
				v7 = v7 % 1 * (2^32 - 1) + v7
				v3 = v3 + v7 + W[perm_blake3[j + 17]]
				vF = XOR(vF, v3) % 2^32 / 2^8
				vF = vF % 1 * (2^32 - 1) + vF
				vB = vB + vF
				v7 = XOR(v7, vB) % 2^32 / 2^7
				v7 = v7 % 1 * (2^32 - 1) + v7
				v0 = v0 + v5 + W[perm_blake3[j + 21]]
				vF = XOR(vF, v0) % 2^32 / 2^16
				vF = vF % 1 * (2^32 - 1) + vF
				vA = vA + vF
				v5 = XOR(v5, vA) % 2^32 / 2^12
				v5 = v5 % 1 * (2^32 - 1) + v5
				v0 = v0 + v5 + W[perm_blake3[j + 5]]
				vF = XOR(vF, v0) % 2^32 / 2^8
				vF = vF % 1 * (2^32 - 1) + vF
				vA = vA + vF
				v5 = XOR(v5, vA) % 2^32 / 2^7
				v5 = v5 % 1 * (2^32 - 1) + v5
				v1 = v1 + v6 + W[perm_blake3[j + 3]]
				vC = XOR(vC, v1) % 2^32 / 2^16
				vC = vC % 1 * (2^32 - 1) + vC
				vB = vB + vC
				v6 = XOR(v6, vB) % 2^32 / 2^12
				v6 = v6 % 1 * (2^32 - 1) + v6
				v1 = v1 + v6 + W[perm_blake3[j + 6]]
				vC = XOR(vC, v1) % 2^32 / 2^8
				vC = vC % 1 * (2^32 - 1) + vC
				vB = vB + vC
				v6 = XOR(v6, vB) % 2^32 / 2^7
				v6 = v6 % 1 * (2^32 - 1) + v6
				v2 = v2 + v7 + W[perm_blake3[j + 4]]
				vD = XOR(vD, v2) % 2^32 / 2^16
				vD = vD % 1 * (2^32 - 1) + vD
				v8 = v8 + vD
				v7 = XOR(v7, v8) % 2^32 / 2^12
				v7 = v7 % 1 * (2^32 - 1) + v7
				v2 = v2 + v7 + W[perm_blake3[j + 18]]
				vD = XOR(vD, v2) % 2^32 / 2^8
				vD = vD % 1 * (2^32 - 1) + vD
				v8 = v8 + vD
				v7 = XOR(v7, v8) % 2^32 / 2^7
				v7 = v7 % 1 * (2^32 - 1) + v7
				v3 = v3 + v4 + W[perm_blake3[j + 19]]
				vE = XOR(vE, v3) % 2^32 / 2^16
				vE = vE % 1 * (2^32 - 1) + vE
				v9 = v9 + vE
				v4 = XOR(v4, v9) % 2^32 / 2^12
				v4 = v4 % 1 * (2^32 - 1) + v4
				v3 = v3 + v4 + W[perm_blake3[j + 20]]
				vE = XOR(vE, v3) % 2^32 / 2^8
				vE = vE % 1 * (2^32 - 1) + vE
				v9 = v9 + vE
				v4 = XOR(v4, v9) % 2^32 / 2^7
				v4 = v4 % 1 * (2^32 - 1) + v4
			end
			if wide_output then
				H_out[ 9] = XOR(h1, v8)
				H_out[10] = XOR(h2, v9)
				H_out[11] = XOR(h3, vA)
				H_out[12] = XOR(h4, vB)
				H_out[13] = XOR(h5, vC)
				H_out[14] = XOR(h6, vD)
				H_out[15] = XOR(h7, vE)
				H_out[16] = XOR(h8, vF)
			end
			h1 = XOR(v0, v8)
			h2 = XOR(v1, v9)
			h3 = XOR(v2, vA)
			h4 = XOR(v3, vB)
			h5 = XOR(v4, vC)
			h6 = XOR(v5, vD)
			h7 = XOR(v6, vE)
			h8 = XOR(v7, vF)
		end
		H_out[1], H_out[2], H_out[3], H_out[4], H_out[5], H_out[6], H_out[7], H_out[8] = h1, h2, h3, h4, h5, h6, h7, h8
	end

end


--------------------------------------------------------------------------------
-- MAGIC NUMBERS CALCULATOR
--------------------------------------------------------------------------------
-- Q:
--    Is 53-bit "double" math enough to calculate square roots and cube roots of primes with 64 correct bits after decimal point?
-- A:
--    Yes, 53-bit "double" arithmetic is enough.
--    We could obtain first 40 bits by direct calculation of p^(1/3) and next 40 bits by one step of Newton's method.

do
	local function mul(src1, src2, factor, result_length)
		-- src1, src2 - long integers (arrays of digits in base 2^24)
		-- factor - small integer
		-- returns long integer result (src1 * src2 * factor) and its floating point approximation
		local result, carry, value, weight = {}, 0.0, 0.0, 1.0
		for j = 1, result_length do
			for k = math_max(1, j + 1 - #src2), math_min(j, #src1) do
				carry = carry + factor * src1[k] * src2[j + 1 - k]  -- "int32" is not enough for multiplication result, that's why "factor" must be of type "double"
			end
			local digit = carry % 2^24
			result[j] = floor(digit)
			carry = (carry - digit) / 2^24
			value = value + digit * weight
			weight = weight * 2^24
		end
		return result, value
	end

	local idx, step, p, one, sqrt_hi, sqrt_lo = 0, {4, 1, 2, -2, 2}, 4, {1}, sha2_H_hi, sha2_H_lo
	repeat
		p = p + step[p % 6]
		local d = 1
		repeat
			d = d + step[d % 6]
			if d*d > p then -- next prime number is found
				local root = p^(1/3)
				local R = root * 2^40
				R = mul({R - R % 1}, one, 1.0, 2)
				local _, delta = mul(R, mul(R, R, 1.0, 4), -1.0, 4)
				local hi = R[2] % 65536 * 65536 + floor(R[1] / 256)
				local lo = R[1] % 256 * 16777216 + floor(delta * (2^-56 / 3) * root / p)
				if idx < 16 then
					root = p^(1/2)
					R = root * 2^40
					R = mul({R - R % 1}, one, 1.0, 2)
					_, delta = mul(R, R, -1.0, 2)
					local hi = R[2] % 65536 * 65536 + floor(R[1] / 256)
					local lo = R[1] % 256 * 16777216 + floor(delta * 2^-17 / root)
					local idx = idx % 8 + 1
					sha2_H_ext256[224][idx] = lo
					sqrt_hi[idx], sqrt_lo[idx] = hi, lo + hi * hi_factor
					if idx > 7 then
						sqrt_hi, sqrt_lo = sha2_H_ext512_hi[384], sha2_H_ext512_lo[384]
					end
				end
				idx = idx + 1
				sha2_K_hi[idx], sha2_K_lo[idx] = hi, lo % K_lo_modulo + hi * hi_factor
				break
			end
		until p % d == 0
	until idx > 79
end

-- Calculating IVs for SHA512/224 and SHA512/256
for width = 224, 256, 32 do
	local H_lo, H_hi = {}
	if HEX64 then
		for j = 1, 8 do
			H_lo[j] = XORA5(sha2_H_lo[j])
		end
	else
		H_hi = {}
		for j = 1, 8 do
			H_lo[j] = XORA5(sha2_H_lo[j])
			H_hi[j] = XORA5(sha2_H_hi[j])
		end
	end
	sha512_feed_128(H_lo, H_hi, "SHA-512/"..tostring(width).."\128"..string_rep("\0", 115).."\88", 0, 128)
	sha2_H_ext512_lo[width] = H_lo
	sha2_H_ext512_hi[width] = H_hi
end

-- Constants for MD5
do
	local sin, abs, modf = math.sin, math.abs, math.modf
	for idx = 1, 64 do
		-- we can't use formula floor(abs(sin(idx))*2^32) because its result may be beyond integer range on Lua built with 32-bit integers
		local hi, lo = modf(abs(sin(idx)) * 2^16)
		md5_K[idx] = hi * 65536 + floor(lo * 2^16)
	end
end

-- Constants for SHA-3
do
	local sh_reg = 29

	local function next_bit()
		local r = sh_reg % 2
		sh_reg = XOR_BYTE((sh_reg - r) / 2, 142 * r)
		return r
	end

	for idx = 1, 24 do
		local lo, m = 0
		for _ = 1, 6 do
			m = m and m * m * 2 or 1
			lo = lo + next_bit() * m
		end
		local hi = next_bit() * m
		sha3_RC_hi[idx], sha3_RC_lo[idx] = hi, lo + hi * hi_factor_keccak
	end
end

if branch == "FFI" then
	sha2_K_hi = ffi.new("uint32_t[?]", #sha2_K_hi + 1, 0, unpack(sha2_K_hi))
	sha2_K_lo = ffi.new("int64_t[?]",  #sha2_K_lo + 1, 0, unpack(sha2_K_lo))
	--md5_K = ffi.new("uint32_t[?]", #md5_K + 1, 0, unpack(md5_K))
	if hi_factor_keccak == 0 then
		sha3_RC_lo = ffi.new("uint32_t[?]", #sha3_RC_lo + 1, 0, unpack(sha3_RC_lo))
		sha3_RC_hi = ffi.new("uint32_t[?]", #sha3_RC_hi + 1, 0, unpack(sha3_RC_hi))
	else
		sha3_RC_lo = ffi.new("int64_t[?]", #sha3_RC_lo + 1, 0, unpack(sha3_RC_lo))
	end
end


--------------------------------------------------------------------------------
-- MAIN FUNCTIONS
--------------------------------------------------------------------------------

local function sha256ext(width, message)
	-- Create an instance (private objects for current calculation)
	local H, length, tail = {unpack(sha2_H_ext256[width])}, 0.0, ""

	local function partial(message_part)
		if message_part then
			if tail then
				length = length + #message_part
				local offs = 0
				if tail ~= "" and #tail + #message_part >= 64 then
					offs = 64 - #tail
					sha256_feed_64(H, tail..sub(message_part, 1, offs), 0, 64)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size % 64
				sha256_feed_64(H, message_part, offs, size - size_tail)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				local final_blocks = {tail, "\128", string_rep("\0", (-9 - length) % 64 + 1)}
				tail = nil
				-- Assuming user data length is shorter than (2^53)-9 bytes
				-- Anyway, it looks very unrealistic that someone would spend more than a year of calculations to process 2^53 bytes of data by using this Lua script :-)
				-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes
				length = length * (8 / 256^7)  -- convert "byte-counter" to "bit-counter" and move decimal point to the left
				for j = 4, 10 do
					length = length % 1 * 256
					final_blocks[j] = char(floor(length))
				end
				final_blocks = table_concat(final_blocks)
				sha256_feed_64(H, final_blocks, 0, #final_blocks)
				local max_reg = width / 32
				for j = 1, max_reg do
					H[j] = HEX(H[j])
				end
				H = table_concat(H, "", 1, max_reg)
			end
			return H
		end
	end

	if message then
		-- Actually perform calculations and return the SHA256 digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get SHA256 digest by invoking this function without an argument
		return partial
	end
end


local function sha512ext(width, message)
	-- Create an instance (private objects for current calculation)
	local length, tail, H_lo, H_hi = 0.0, "", {unpack(sha2_H_ext512_lo[width])}, not HEX64 and {unpack(sha2_H_ext512_hi[width])}

	local function partial(message_part)
		if message_part then
			if tail then
				length = length + #message_part
				local offs = 0
				if tail ~= "" and #tail + #message_part >= 128 then
					offs = 128 - #tail
					sha512_feed_128(H_lo, H_hi, tail..sub(message_part, 1, offs), 0, 128)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size % 128
				sha512_feed_128(H_lo, H_hi, message_part, offs, size - size_tail)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				local final_blocks = {tail, "\128", string_rep("\0", (-17-length) % 128 + 9)}
				tail = nil
				-- Assuming user data length is shorter than (2^53)-17 bytes
				-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes
				length = length * (8 / 256^7)  -- convert "byte-counter" to "bit-counter" and move floating point to the left
				for j = 4, 10 do
					length = length % 1 * 256
					final_blocks[j] = char(floor(length))
				end
				final_blocks = table_concat(final_blocks)
				sha512_feed_128(H_lo, H_hi, final_blocks, 0, #final_blocks)
				local max_reg = ceil(width / 64)
				if HEX64 then
					for j = 1, max_reg do
						H_lo[j] = HEX64(H_lo[j])
					end
				else
					for j = 1, max_reg do
						H_lo[j] = HEX(H_hi[j])..HEX(H_lo[j])
					end
					H_hi = nil
				end
				H_lo = sub(table_concat(H_lo, "", 1, max_reg), 1, width / 4)
			end
			return H_lo
		end
	end

	if message then
		-- Actually perform calculations and return the SHA512 digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get SHA512 digest by invoking this function without an argument
		return partial
	end
end


local function md5(message)
	-- Create an instance (private objects for current calculation)
	local H, length, tail = {unpack(md5_sha1_H, 1, 4)}, 0.0, ""

	local function partial(message_part)
		if message_part then
			if tail then
				length = length + #message_part
				local offs = 0
				if tail ~= "" and #tail + #message_part >= 64 then
					offs = 64 - #tail
					md5_feed_64(H, tail..sub(message_part, 1, offs), 0, 64)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size % 64
				md5_feed_64(H, message_part, offs, size - size_tail)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				local final_blocks = {tail, "\128", string_rep("\0", (-9 - length) % 64)}
				tail = nil
				length = length * 8  -- convert "byte-counter" to "bit-counter"
				for j = 4, 11 do
					local low_byte = length % 256
					final_blocks[j] = char(low_byte)
					length = (length - low_byte) / 256
				end
				final_blocks = table_concat(final_blocks)
				md5_feed_64(H, final_blocks, 0, #final_blocks)
				for j = 1, 4 do
					H[j] = HEX(H[j])
				end
				H = gsub(table_concat(H), "(..)(..)(..)(..)", "%4%3%2%1")
			end
			return H
		end
	end

	if message then
		-- Actually perform calculations and return the MD5 digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get MD5 digest by invoking this function without an argument
		return partial
	end
end


local function sha1(message)
	-- Create an instance (private objects for current calculation)
	local H, length, tail = {unpack(md5_sha1_H)}, 0.0, ""

	local function partial(message_part)
		if message_part then
			if tail then
				length = length + #message_part
				local offs = 0
				if tail ~= "" and #tail + #message_part >= 64 then
					offs = 64 - #tail
					sha1_feed_64(H, tail..sub(message_part, 1, offs), 0, 64)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size % 64
				sha1_feed_64(H, message_part, offs, size - size_tail)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				local final_blocks = {tail, "\128", string_rep("\0", (-9 - length) % 64 + 1)}
				tail = nil
				-- Assuming user data length is shorter than (2^53)-9 bytes
				-- 2^53 bytes = 2^56 bits, so "bit-counter" fits in 7 bytes
				length = length * (8 / 256^7)  -- convert "byte-counter" to "bit-counter" and move decimal point to the left
				for j = 4, 10 do
					length = length % 1 * 256
					final_blocks[j] = char(floor(length))
				end
				final_blocks = table_concat(final_blocks)
				sha1_feed_64(H, final_blocks, 0, #final_blocks)
				for j = 1, 5 do
					H[j] = HEX(H[j])
				end
				H = table_concat(H)
			end
			return H
		end
	end

	if message then
		-- Actually perform calculations and return the SHA-1 digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get SHA-1 digest by invoking this function without an argument
		return partial
	end
end


local function keccak(block_size_in_bytes, digest_size_in_bytes, is_SHAKE, message)
	-- "block_size_in_bytes" is multiple of 8
	if type(digest_size_in_bytes) ~= "number" then
		-- arguments in SHAKE are swapped:
		--    NIST FIPS 202 defines SHAKE(message,num_bits)
		--    this module   defines SHAKE(num_bytes,message)
		-- it's easy to forget about this swap, hence the check
		error("Argument 'digest_size_in_bytes' must be a number", 2)
	end
	-- Create an instance (private objects for current calculation)
	local tail, lanes_lo, lanes_hi = "", create_array_of_lanes(), hi_factor_keccak == 0 and create_array_of_lanes()
	local result

	local function partial(message_part)
		if message_part then
			if tail then
				local offs = 0
				if tail ~= "" and #tail + #message_part >= block_size_in_bytes then
					offs = block_size_in_bytes - #tail
					keccak_feed(lanes_lo, lanes_hi, tail..sub(message_part, 1, offs), 0, block_size_in_bytes, block_size_in_bytes)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size % block_size_in_bytes
				keccak_feed(lanes_lo, lanes_hi, message_part, offs, size - size_tail, block_size_in_bytes)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				-- append the following bits to the message: for usual SHA-3: 011(0*)1, for SHAKE: 11111(0*)1
				local gap_start = is_SHAKE and 31 or 6
				tail = tail..(#tail + 1 == block_size_in_bytes and char(gap_start + 128) or char(gap_start)..string_rep("\0", (-2 - #tail) % block_size_in_bytes).."\128")
				keccak_feed(lanes_lo, lanes_hi, tail, 0, #tail, block_size_in_bytes)
				tail = nil
				local lanes_used = 0
				local total_lanes = floor(block_size_in_bytes / 8)
				local qwords = {}

				local function get_next_qwords_of_digest(qwords_qty)
					-- returns not more than 'qwords_qty' qwords ('qwords_qty' might be non-integer)
					-- doesn't go across keccak-buffer boundary
					-- block_size_in_bytes is a multiple of 8, so, keccak-buffer contains integer number of qwords
					if lanes_used >= total_lanes then
						keccak_feed(lanes_lo, lanes_hi, "\0\0\0\0\0\0\0\0", 0, 8, 8)
						lanes_used = 0
					end
					qwords_qty = floor(math_min(qwords_qty, total_lanes - lanes_used))
					if hi_factor_keccak ~= 0 then
						for j = 1, qwords_qty do
							qwords[j] = HEX64(lanes_lo[lanes_used + j - 1 + lanes_index_base])
						end
					else
						for j = 1, qwords_qty do
							qwords[j] = HEX(lanes_hi[lanes_used + j])..HEX(lanes_lo[lanes_used + j])
						end
					end
					lanes_used = lanes_used + qwords_qty
					return
						gsub(table_concat(qwords, "", 1, qwords_qty), "(..)(..)(..)(..)(..)(..)(..)(..)", "%8%7%6%5%4%3%2%1"),
					qwords_qty * 8
				end

				local parts = {}      -- digest parts
				local last_part, last_part_size = "", 0

				local function get_next_part_of_digest(bytes_needed)
					-- returns 'bytes_needed' bytes, for arbitrary integer 'bytes_needed'
					bytes_needed = bytes_needed or 1
					if bytes_needed <= last_part_size then
						last_part_size = last_part_size - bytes_needed
						local part_size_in_nibbles = bytes_needed * 2
						local result = sub(last_part, 1, part_size_in_nibbles)
						last_part = sub(last_part, part_size_in_nibbles + 1)
						return result
					end
					local parts_qty = 0
					if last_part_size > 0 then
						parts_qty = 1
						parts[parts_qty] = last_part
						bytes_needed = bytes_needed - last_part_size
					end
					-- repeats until the length is enough
					while bytes_needed >= 8 do
						local next_part, next_part_size = get_next_qwords_of_digest(bytes_needed / 8)
						parts_qty = parts_qty + 1
						parts[parts_qty] = next_part
						bytes_needed = bytes_needed - next_part_size
					end
					if bytes_needed > 0 then
						last_part, last_part_size = get_next_qwords_of_digest(1)
						parts_qty = parts_qty + 1
						parts[parts_qty] = get_next_part_of_digest(bytes_needed)
					else
						last_part, last_part_size = "", 0
					end
					return table_concat(parts, "", 1, parts_qty)
				end

				if digest_size_in_bytes < 0 then
					result = get_next_part_of_digest
				else
					result = get_next_part_of_digest(digest_size_in_bytes)
				end
			end
			return result
		end
	end

	if message then
		-- Actually perform calculations and return the SHA-3 digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get SHA-3 digest by invoking this function without an argument
		return partial
	end
end


local hex_to_bin, bin_to_hex, bin_to_base64, base64_to_bin
do
	function hex_to_bin(hex_string)
		return (gsub(hex_string, "%x%x",
			function (hh)
				return char(tonumber(hh, 16))
			end
			))
	end

	function bin_to_hex(binary_string)
		return (gsub(binary_string, ".",
			function (c)
				return string_format("%02x", byte(c))
			end
			))
	end

	local base64_symbols = {
		['+'] = 62, ['-'] = 62,  [62] = '+',
		['/'] = 63, ['_'] = 63,  [63] = '/',
		['='] = -1, ['.'] = -1,  [-1] = '='
	}
	local symbol_index = 0
	for j, pair in ipairs{'AZ', 'az', '09'} do
		for ascii = byte(pair), byte(pair, 2) do
			local ch = char(ascii)
			base64_symbols[ch] = symbol_index
			base64_symbols[symbol_index] = ch
			symbol_index = symbol_index + 1
		end
	end

	function bin_to_base64(binary_string)
		local result = {}
		for pos = 1, #binary_string, 3 do
			local c1, c2, c3, c4 = byte(sub(binary_string, pos, pos + 2)..'\0', 1, -1)
			result[#result + 1] =
				base64_symbols[floor(c1 / 4)]
				..base64_symbols[c1 % 4 * 16 + floor(c2 / 16)]
				..base64_symbols[c3 and c2 % 16 * 4 + floor(c3 / 64) or -1]
				..base64_symbols[c4 and c3 % 64 or -1]
		end
		return table_concat(result)
	end

	function base64_to_bin(base64_string)
		local result, chars_qty = {}, 3
		for pos, ch in gmatch(gsub(base64_string, '%s+', ''), '()(.)') do
			local code = base64_symbols[ch]
			if code < 0 then
				chars_qty = chars_qty - 1
				code = 0
			end
			local idx = pos % 4
			if idx > 0 then
				result[-idx] = code
			else
				local c1 = result[-1] * 4 + floor(result[-2] / 16)
				local c2 = (result[-2] % 16) * 16 + floor(result[-3] / 4)
				local c3 = (result[-3] % 4) * 64 + code
				result[#result + 1] = sub(char(c1, c2, c3), 1, chars_qty)
			end
		end
		return table_concat(result)
	end

end


local block_size_for_HMAC  -- this table will be initialized at the end of the module

local function pad_and_xor(str, result_length, byte_for_xor)
	return gsub(str, ".",
		function(c)
			return char(XOR_BYTE(byte(c), byte_for_xor))
		end
	)..string_rep(char(byte_for_xor), result_length - #str)
end

local function hmac(hash_func, key, message)
	-- Create an instance (private objects for current calculation)
	local block_size = block_size_for_HMAC[hash_func]
	if not block_size then
		error("Unknown hash function", 2)
	end
	if #key > block_size then
		key = hex_to_bin(hash_func(key))
	end
	local append = hash_func()(pad_and_xor(key, block_size, 0x36))
	local result

	local function partial(message_part)
		if not message_part then
			result = result or hash_func(pad_and_xor(key, block_size, 0x5C)..hex_to_bin(append()))
			return result
		elseif result then
			error("Adding more chunks is not allowed after receiving the result", 2)
		else
			append(message_part)
			return partial
		end
	end

	if message then
		-- Actually perform calculations and return the HMAC of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading of a message
		-- User should feed every chunk of the message as single argument to this function and finally get HMAC by invoking this function without an argument
		return partial
	end
end


local function xor_blake2_salt(salt, letter, H_lo, H_hi)
	-- salt: concatenation of "Salt"+"Personalization" fields
	local max_size = letter == "s" and 16 or 32
	local salt_size = #salt
	if salt_size > max_size then
		error(string_format("For BLAKE2%s/BLAKE2%sp/BLAKE2X%s the 'salt' parameter length must not exceed %d bytes", letter, letter, letter, max_size), 2)
	end
	if H_lo then
		local offset, blake2_word_size, xor = 0, letter == "s" and 4 or 8, letter == "s" and XOR or XORA5
		for j = 5, 4 + ceil(salt_size / blake2_word_size) do
			local prev, last
			for _ = 1, blake2_word_size, 4 do
				offset = offset + 4
				local a, b, c, d = byte(salt, offset - 3, offset)
				local four_bytes = (((d or 0) * 256 + (c or 0)) * 256 + (b or 0)) * 256 + (a or 0)
				prev, last = last, four_bytes
			end
			H_lo[j] = xor(H_lo[j], prev and last * hi_factor + prev or last)
			if H_hi then
				H_hi[j] = xor(H_hi[j], last)
			end
		end
	end
end

local function blake2s(message, key, salt, digest_size_in_bytes, XOF_length, B2_offset)
	-- message:  binary string to be hashed (or nil for "chunk-by-chunk" input mode)
	-- key:      (optional) binary string up to 32 bytes, by default empty string
	-- salt:     (optional) binary string up to 16 bytes, by default empty string
	-- digest_size_in_bytes: (optional) integer from 1 to 32, by default 32
	-- The last two parameters "XOF_length" and "B2_offset" are for internal use only, user must omit them (or pass nil)
	digest_size_in_bytes = digest_size_in_bytes or 32
	if digest_size_in_bytes < 1 or digest_size_in_bytes > 32 then
		error("BLAKE2s digest length must be from 1 to 32 bytes", 2)
	end
	key = key or ""
	local key_length = #key
	if key_length > 32 then
		error("BLAKE2s key length must not exceed 32 bytes", 2)
	end
	salt = salt or ""
	local bytes_compressed, tail, H = 0.0, "", {unpack(sha2_H_hi)}
	if B2_offset then
		H[1] = XOR(H[1], digest_size_in_bytes)
		H[2] = XOR(H[2], 0x20)
		H[3] = XOR(H[3], B2_offset)
		H[4] = XOR(H[4], 0x20000000 + XOF_length)
	else
		H[1] = XOR(H[1], 0x01010000 + key_length * 256 + digest_size_in_bytes)
		if XOF_length then
			H[4] = XOR(H[4], XOF_length)
		end
	end
	if salt ~= "" then
		xor_blake2_salt(salt, "s", H)
	end

	local function partial(message_part)
		if message_part then
			if tail then
				local offs = 0
				if tail ~= "" and #tail + #message_part > 64 then
					offs = 64 - #tail
					bytes_compressed = blake2s_feed_64(H, tail..sub(message_part, 1, offs), 0, 64, bytes_compressed)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size > 0 and (size - 1) % 64 + 1 or 0
				bytes_compressed = blake2s_feed_64(H, message_part, offs, size - size_tail, bytes_compressed)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				if B2_offset then
					blake2s_feed_64(H, nil, 0, 64, 0, 32)
				else
					blake2s_feed_64(H, tail..string_rep("\0", 64 - #tail), 0, 64, bytes_compressed, #tail)
				end
				tail = nil
				if not XOF_length or B2_offset then
					local max_reg = ceil(digest_size_in_bytes / 4)
					for j = 1, max_reg do
						H[j] = HEX(H[j])
					end
					H = sub(gsub(table_concat(H, "", 1, max_reg), "(..)(..)(..)(..)", "%4%3%2%1"), 1, digest_size_in_bytes * 2)
				end
			end
			return H
		end
	end

	if key_length > 0 then
		partial(key..string_rep("\0", 64 - key_length))
	end
	if B2_offset then
		return partial()
	elseif message then
		-- Actually perform calculations and return the BLAKE2s digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get BLAKE2s digest by invoking this function without an argument
		return partial
	end
end

local function blake2b(message, key, salt, digest_size_in_bytes, XOF_length, B2_offset)
	-- message:  binary string to be hashed (or nil for "chunk-by-chunk" input mode)
	-- key:      (optional) binary string up to 64 bytes, by default empty string
	-- salt:     (optional) binary string up to 32 bytes, by default empty string
	-- digest_size_in_bytes: (optional) integer from 1 to 64, by default 64
	-- The last two parameters "XOF_length" and "B2_offset" are for internal use only, user must omit them (or pass nil)
	digest_size_in_bytes = floor(digest_size_in_bytes or 64)
	if digest_size_in_bytes < 1 or digest_size_in_bytes > 64 then
		error("BLAKE2b digest length must be from 1 to 64 bytes", 2)
	end
	key = key or ""
	local key_length = #key
	if key_length > 64 then
		error("BLAKE2b key length must not exceed 64 bytes", 2)
	end
	salt = salt or ""
	local bytes_compressed, tail, H_lo, H_hi = 0.0, "", {unpack(sha2_H_lo)}, not HEX64 and {unpack(sha2_H_hi)}
	if B2_offset then
		if H_hi then
			H_lo[1] = XORA5(H_lo[1], digest_size_in_bytes)
			H_hi[1] = XORA5(H_hi[1], 0x40)
			H_lo[2] = XORA5(H_lo[2], B2_offset)
			H_hi[2] = XORA5(H_hi[2], XOF_length)
		else
			H_lo[1] = XORA5(H_lo[1], 0x40 * hi_factor + digest_size_in_bytes)
			H_lo[2] = XORA5(H_lo[2], XOF_length * hi_factor + B2_offset)
		end
		H_lo[3] = XORA5(H_lo[3], 0x4000)
	else
		H_lo[1] = XORA5(H_lo[1], 0x01010000 + key_length * 256 + digest_size_in_bytes)
		if XOF_length then
			if H_hi then
				H_hi[2] = XORA5(H_hi[2], XOF_length)
			else
				H_lo[2] = XORA5(H_lo[2], XOF_length * hi_factor)
			end
		end
	end
	if salt ~= "" then
		xor_blake2_salt(salt, "b", H_lo, H_hi)
	end

	local function partial(message_part)
		if message_part then
			if tail then
				local offs = 0
				if tail ~= "" and #tail + #message_part > 128 then
					offs = 128 - #tail
					bytes_compressed = blake2b_feed_128(H_lo, H_hi, tail..sub(message_part, 1, offs), 0, 128, bytes_compressed)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size > 0 and (size - 1) % 128 + 1 or 0
				bytes_compressed = blake2b_feed_128(H_lo, H_hi, message_part, offs, size - size_tail, bytes_compressed)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				if B2_offset then
					blake2b_feed_128(H_lo, H_hi, nil, 0, 128, 0, 64)
				else
					blake2b_feed_128(H_lo, H_hi, tail..string_rep("\0", 128 - #tail), 0, 128, bytes_compressed, #tail)
				end
				tail = nil
				if XOF_length and not B2_offset then
					if H_hi then
						for j = 8, 1, -1 do
							H_lo[j*2] = H_hi[j]
							H_lo[j*2-1] = H_lo[j]
						end
						return H_lo, 16
					end
				else
					local max_reg = ceil(digest_size_in_bytes / 8)
					if H_hi then
						for j = 1, max_reg do
							H_lo[j] = HEX(H_hi[j])..HEX(H_lo[j])
						end
					else
						for j = 1, max_reg do
							H_lo[j] = HEX64(H_lo[j])
						end
					end
					H_lo = sub(gsub(table_concat(H_lo, "", 1, max_reg), "(..)(..)(..)(..)(..)(..)(..)(..)", "%8%7%6%5%4%3%2%1"), 1, digest_size_in_bytes * 2)
				end
				H_hi = nil
			end
			return H_lo
		end
	end

	if key_length > 0 then
		partial(key..string_rep("\0", 128 - key_length))
	end
	if B2_offset then
		return partial()
	elseif message then
		-- Actually perform calculations and return the BLAKE2b digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get BLAKE2b digest by invoking this function without an argument
		return partial
	end
end

local function blake2sp(message, key, salt, digest_size_in_bytes)
	-- message:  binary string to be hashed (or nil for "chunk-by-chunk" input mode)
	-- key:      (optional) binary string up to 32 bytes, by default empty string
	-- salt:     (optional) binary string up to 16 bytes, by default empty string
	-- digest_size_in_bytes: (optional) integer from 1 to 32, by default 32
	digest_size_in_bytes = digest_size_in_bytes or 32
	if digest_size_in_bytes < 1 or digest_size_in_bytes > 32 then
		error("BLAKE2sp digest length must be from 1 to 32 bytes", 2)
	end
	key = key or ""
	local key_length = #key
	if key_length > 32 then
		error("BLAKE2sp key length must not exceed 32 bytes", 2)
	end
	salt = salt or ""
	local instances, length, first_dword_of_parameter_block, result = {}, 0.0, 0x02080000 + key_length * 256 + digest_size_in_bytes
	for j = 1, 8 do
		local bytes_compressed, tail, H = 0.0, "", {unpack(sha2_H_hi)}
		instances[j] = {bytes_compressed, tail, H}
		H[1] = XOR(H[1], first_dword_of_parameter_block)
		H[3] = XOR(H[3], j-1)
		H[4] = XOR(H[4], 0x20000000)
		if salt ~= "" then
			xor_blake2_salt(salt, "s", H)
		end
	end

	local function partial(message_part)
		if message_part then
			if instances then
				local from = 0
				while true do
					local to = math_min(from + 64 - length % 64, #message_part)
					if to > from then
						local inst = instances[floor(length / 64) % 8 + 1]
						local part = sub(message_part, from + 1, to)
						length, from = length + to - from, to
						local bytes_compressed, tail = inst[1], inst[2]
						if #tail < 64 then
							tail = tail..part
						else
							local H = inst[3]
							bytes_compressed = blake2s_feed_64(H, tail, 0, 64, bytes_compressed)
							tail = part
						end
						inst[1], inst[2] = bytes_compressed, tail
					else
						break
					end
				end
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if instances then
				local root_H = {unpack(sha2_H_hi)}
				root_H[1] = XOR(root_H[1], first_dword_of_parameter_block)
				root_H[4] = XOR(root_H[4], 0x20010000)
				if salt ~= "" then
					xor_blake2_salt(salt, "s", root_H)
				end
				for j = 1, 8 do
					local inst = instances[j]
					local bytes_compressed, tail, H = inst[1], inst[2], inst[3]
					blake2s_feed_64(H, tail..string_rep("\0", 64 - #tail), 0, 64, bytes_compressed, #tail, j == 8)
					if j % 2 == 0 then
						local index = 0
						for k = j - 1, j do
							local inst = instances[k]
							local H = inst[3]
							for i = 1, 8 do
								index = index + 1
								common_W_blake2s[index] = H[i]
							end
						end
						blake2s_feed_64(root_H, nil, 0, 64, 64 * (j/2 - 1), j == 8 and 64, j == 8)
					end
				end
				instances = nil
				local max_reg = ceil(digest_size_in_bytes / 4)
				for j = 1, max_reg do
					root_H[j] = HEX(root_H[j])
				end
				result = sub(gsub(table_concat(root_H, "", 1, max_reg), "(..)(..)(..)(..)", "%4%3%2%1"), 1, digest_size_in_bytes * 2)
			end
			return result
		end
	end

	if key_length > 0 then
		key = key..string_rep("\0", 64 - key_length)
		for j = 1, 8 do
			partial(key)
		end
	end
	if message then
		-- Actually perform calculations and return the BLAKE2sp digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get BLAKE2sp digest by invoking this function without an argument
		return partial
	end

end

local function blake2bp(message, key, salt, digest_size_in_bytes)
	-- message:  binary string to be hashed (or nil for "chunk-by-chunk" input mode)
	-- key:      (optional) binary string up to 64 bytes, by default empty string
	-- salt:     (optional) binary string up to 32 bytes, by default empty string
	-- digest_size_in_bytes: (optional) integer from 1 to 64, by default 64
	digest_size_in_bytes = digest_size_in_bytes or 64
	if digest_size_in_bytes < 1 or digest_size_in_bytes > 64 then
		error("BLAKE2bp digest length must be from 1 to 64 bytes", 2)
	end
	key = key or ""
	local key_length = #key
	if key_length > 64 then
		error("BLAKE2bp key length must not exceed 64 bytes", 2)
	end
	salt = salt or ""
	local instances, length, first_dword_of_parameter_block, result = {}, 0.0, 0x02040000 + key_length * 256 + digest_size_in_bytes
	for j = 1, 4 do
		local bytes_compressed, tail, H_lo, H_hi = 0.0, "", {unpack(sha2_H_lo)}, not HEX64 and {unpack(sha2_H_hi)}
		instances[j] = {bytes_compressed, tail, H_lo, H_hi}
		H_lo[1] = XORA5(H_lo[1], first_dword_of_parameter_block)
		H_lo[2] = XORA5(H_lo[2], j-1)
		H_lo[3] = XORA5(H_lo[3], 0x4000)
		if salt ~= "" then
			xor_blake2_salt(salt, "b", H_lo, H_hi)
		end
	end

	local function partial(message_part)
		if message_part then
			if instances then
				local from = 0
				while true do
					local to = math_min(from + 128 - length % 128, #message_part)
					if to > from then
						local inst = instances[floor(length / 128) % 4 + 1]
						local part = sub(message_part, from + 1, to)
						length, from = length + to - from, to
						local bytes_compressed, tail = inst[1], inst[2]
						if #tail < 128 then
							tail = tail..part
						else
							local H_lo, H_hi = inst[3], inst[4]
							bytes_compressed = blake2b_feed_128(H_lo, H_hi, tail, 0, 128, bytes_compressed)
							tail = part
						end
						inst[1], inst[2] = bytes_compressed, tail
					else
						break
					end
				end
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if instances then
				local root_H_lo, root_H_hi = {unpack(sha2_H_lo)}, not HEX64 and {unpack(sha2_H_hi)}
				root_H_lo[1] = XORA5(root_H_lo[1], first_dword_of_parameter_block)
				root_H_lo[3] = XORA5(root_H_lo[3], 0x4001)
				if salt ~= "" then
					xor_blake2_salt(salt, "b", root_H_lo, root_H_hi)
				end
				for j = 1, 4 do
					local inst = instances[j]
					local bytes_compressed, tail, H_lo, H_hi = inst[1], inst[2], inst[3], inst[4]
					blake2b_feed_128(H_lo, H_hi, tail..string_rep("\0", 128 - #tail), 0, 128, bytes_compressed, #tail, j == 4)
					if j % 2 == 0 then
						local index = 0
						for k = j - 1, j do
							local inst = instances[k]
							local H_lo, H_hi = inst[3], inst[4]
							for i = 1, 8 do
								index = index + 1
								common_W_blake2b[index] = H_lo[i]
								if H_hi then
									index = index + 1
									common_W_blake2b[index] = H_hi[i]
								end
							end
						end
						blake2b_feed_128(root_H_lo, root_H_hi, nil, 0, 128, 128 * (j/2 - 1), j == 4 and 128, j == 4)
					end
				end
				instances = nil
				local max_reg = ceil(digest_size_in_bytes / 8)
				if HEX64 then
					for j = 1, max_reg do
						root_H_lo[j] = HEX64(root_H_lo[j])
					end
				else
					for j = 1, max_reg do
						root_H_lo[j] = HEX(root_H_hi[j])..HEX(root_H_lo[j])
					end
				end
				result = sub(gsub(table_concat(root_H_lo, "", 1, max_reg), "(..)(..)(..)(..)(..)(..)(..)(..)", "%8%7%6%5%4%3%2%1"), 1, digest_size_in_bytes * 2)
			end
			return result
		end
	end

	if key_length > 0 then
		key = key..string_rep("\0", 128 - key_length)
		for j = 1, 4 do
			partial(key)
		end
	end
	if message then
		-- Actually perform calculations and return the BLAKE2bp digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get BLAKE2bp digest by invoking this function without an argument
		return partial
	end

end

local function blake2x(inner_func, inner_func_letter, common_W_blake2, block_size, digest_size_in_bytes, message, key, salt)
	local XOF_digest_length_limit, XOF_digest_length, chunk_by_chunk_output = 2^(block_size / 2) - 1
	if digest_size_in_bytes == -1 then  -- infinite digest
		digest_size_in_bytes = math_huge
		XOF_digest_length = floor(XOF_digest_length_limit)
		chunk_by_chunk_output = true
	else
		if digest_size_in_bytes < 0 then
			digest_size_in_bytes = -1.0 * digest_size_in_bytes
			chunk_by_chunk_output = true
		end
		XOF_digest_length = floor(digest_size_in_bytes)
		if XOF_digest_length >= XOF_digest_length_limit then
			error("Requested digest is too long.  BLAKE2X"..inner_func_letter.." finite digest is limited by (2^"..floor(block_size / 2)..")-2 bytes.  Hint: you can generate infinite digest.", 2)
		end
	end
	salt = salt or ""
	if salt ~= "" then
		xor_blake2_salt(salt, inner_func_letter)  -- don't xor, only check the size of salt
	end
	local inner_partial = inner_func(nil, key, salt, nil, XOF_digest_length)
	local result

	local function partial(message_part)
		if message_part then
			if inner_partial then
				inner_partial(message_part)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if inner_partial then
				local half_W, half_W_size = inner_partial()
				half_W_size, inner_partial = half_W_size or 8

				local function get_hash_block(block_no)
					-- block_no = 0...(2^32-1)
					local size = math_min(block_size, digest_size_in_bytes - block_no * block_size)
					if size <= 0 then
						return ""
					end
					for j = 1, half_W_size do
						common_W_blake2[j] = half_W[j]
					end
					for j = half_W_size + 1, 2 * half_W_size do
						common_W_blake2[j] = 0
					end
					return inner_func(nil, nil, salt, size, XOF_digest_length, floor(block_no))
				end

				local hash = {}
				if chunk_by_chunk_output then
					local pos, period, cached_block_no, cached_block = 0, block_size * 2^32

					local function get_next_part_of_digest(arg1, arg2)
						if arg1 == "seek" then
							-- Usage #1:  get_next_part_of_digest("seek", new_pos)
							pos = arg2 % period
						else
							-- Usage #2:  hex_string = get_next_part_of_digest(size)
							local size, index = arg1 or 1, 0
							while size > 0 do
								local block_offset = pos % block_size
								local block_no = (pos - block_offset) / block_size
								local part_size = math_min(size, block_size - block_offset)
								if cached_block_no ~= block_no then
									cached_block_no = block_no
									cached_block = get_hash_block(block_no)
								end
								index = index + 1
								hash[index] = sub(cached_block, block_offset * 2 + 1, (block_offset + part_size) * 2)
								size = size - part_size
								pos = (pos + part_size) % period
							end
							return table_concat(hash, "", 1, index)
						end
					end

					result = get_next_part_of_digest
				else
					for j = 1.0, ceil(digest_size_in_bytes / block_size) do
						hash[j] = get_hash_block(j - 1.0)
					end
					result = table_concat(hash)
				end
			end
			return result
		end
	end

	if message then
		-- Actually perform calculations and return the BLAKE2X digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get BLAKE2X digest by invoking this function without an argument
		return partial
	end
end

local function blake2xs(digest_size_in_bytes, message, key, salt)
	-- digest_size_in_bytes:
	--    0..65534       = get finite digest as single Lua string
	--    (-1)           = get infinite digest in "chunk-by-chunk" output mode
	--    (-2)..(-65534) = get finite digest in "chunk-by-chunk" output mode
	-- message:  binary string to be hashed (or nil for "chunk-by-chunk" input mode)
	-- key:      (optional) binary string up to 32 bytes, by default empty string
	-- salt:     (optional) binary string up to 16 bytes, by default empty string
	return blake2x(blake2s, "s", common_W_blake2s, 32, digest_size_in_bytes, message, key, salt)
end

local function blake2xb(digest_size_in_bytes, message, key, salt)
	-- digest_size_in_bytes:
	--    0..4294967294       = get finite digest as single Lua string
	--    (-1)                = get infinite digest in "chunk-by-chunk" output mode
	--    (-2)..(-4294967294) = get finite digest in "chunk-by-chunk" output mode
	-- message:  binary string to be hashed (or nil for "chunk-by-chunk" input mode)
	-- key:      (optional) binary string up to 64 bytes, by default empty string
	-- salt:     (optional) binary string up to 32 bytes, by default empty string
	return blake2x(blake2b, "b", common_W_blake2b, 64, digest_size_in_bytes, message, key, salt)
end


local function blake3(message, key, digest_size_in_bytes, message_flags, K, return_array)
	-- message:  binary string to be hashed (or nil for "chunk-by-chunk" input mode)
	-- key:      (optional) binary string up to 32 bytes, by default empty string
	-- digest_size_in_bytes: (optional) by default 32
	--    0,1,2,3,4,...  = get finite digest as single Lua string
	--    (-1)           = get infinite digest in "chunk-by-chunk" output mode
	--    -2,-3,-4,...   = get finite digest in "chunk-by-chunk" output mode
	-- The last three parameters "message_flags", "K" and "return_array" are for internal use only, user must omit them (or pass nil)
	key = key or ""
	digest_size_in_bytes = digest_size_in_bytes or 32
	message_flags = message_flags or 0
	if key == "" then
		K = K or sha2_H_hi
	else
		local key_length = #key
		if key_length > 32 then
			error("BLAKE3 key length must not exceed 32 bytes", 2)
		end
		key = key..string_rep("\0", 32 - key_length)
		K = {}
		for j = 1, 8 do
			local a, b, c, d = byte(key, 4*j-3, 4*j)
			K[j] = ((d * 256 + c) * 256 + b) * 256 + a
		end
		message_flags = message_flags + 16  -- flag:KEYED_HASH
	end
	local tail, H, chunk_index, blocks_in_chunk, stack_size, stack = "", {}, 0, 0, 0, {}
	local final_H_in, final_block_length, chunk_by_chunk_output, result, wide_output = K
	local final_compression_flags = 3      -- flags:CHUNK_START,CHUNK_END

	local function feed_blocks(str, offs, size)
		-- size >= 0, size is multiple of 64
		while size > 0 do
			local part_size_in_blocks, block_flags, H_in = 1, 0, H
			if blocks_in_chunk == 0 then
				block_flags = 1               -- flag:CHUNK_START
				H_in, final_H_in = K, H
				final_compression_flags = 2   -- flag:CHUNK_END
			elseif blocks_in_chunk == 15 then
				block_flags = 2               -- flag:CHUNK_END
				final_compression_flags = 3   -- flags:CHUNK_START,CHUNK_END
				final_H_in = K
			else
				part_size_in_blocks = math_min(size / 64, 15 - blocks_in_chunk)
			end
			local part_size = part_size_in_blocks * 64
			blake3_feed_64(str, offs, part_size, message_flags + block_flags, chunk_index, H_in, H)
			offs, size = offs + part_size, size - part_size
			blocks_in_chunk = (blocks_in_chunk + part_size_in_blocks) % 16
			if blocks_in_chunk == 0 then
				-- completing the currect chunk
				chunk_index = chunk_index + 1.0
				local divider = 2.0
				while chunk_index % divider == 0 do
					divider = divider * 2.0
					stack_size = stack_size - 8
					for j = 1, 8 do
						common_W_blake2s[j] = stack[stack_size + j]
					end
					for j = 1, 8 do
						common_W_blake2s[j + 8] = H[j]
					end
					blake3_feed_64(nil, 0, 64, message_flags + 4, 0, K, H)  -- flag:PARENT
				end
				for j = 1, 8 do
					stack[stack_size + j] = H[j]
				end
				stack_size = stack_size + 8
			end
		end
	end

	local function get_hash_block(block_no)
		local size = math_min(64, digest_size_in_bytes - block_no * 64)
		if block_no < 0 or size <= 0 then
			return ""
		end
		if chunk_by_chunk_output then
			for j = 1, 16 do
				common_W_blake2s[j] = stack[j + 16]
			end
		end
		blake3_feed_64(nil, 0, 64, final_compression_flags, block_no, final_H_in, stack, wide_output, final_block_length)
		if return_array then
			return stack
		end
		local max_reg = ceil(size / 4)
		for j = 1, max_reg do
			stack[j] = HEX(stack[j])
		end
		return sub(gsub(table_concat(stack, "", 1, max_reg), "(..)(..)(..)(..)", "%4%3%2%1"), 1, size * 2)
	end

	local function partial(message_part)
		if message_part then
			if tail then
				local offs = 0
				if tail ~= "" and #tail + #message_part > 64 then
					offs = 64 - #tail
					feed_blocks(tail..sub(message_part, 1, offs), 0, 64)
					tail = ""
				end
				local size = #message_part - offs
				local size_tail = size > 0 and (size - 1) % 64 + 1 or 0
				feed_blocks(message_part, offs, size - size_tail)
				tail = tail..sub(message_part, #message_part + 1 - size_tail)
				return partial
			else
				error("Adding more chunks is not allowed after receiving the result", 2)
			end
		else
			if tail then
				final_block_length = #tail
				tail = tail..string_rep("\0", 64 - #tail)
				if common_W_blake2s[0] then
					for j = 1, 16 do
						local a, b, c, d = byte(tail, 4*j-3, 4*j)
						common_W_blake2s[j] = OR(SHL(d, 24), SHL(c, 16), SHL(b, 8), a)
					end
				else
					for j = 1, 16 do
						local a, b, c, d = byte(tail, 4*j-3, 4*j)
						common_W_blake2s[j] = ((d * 256 + c) * 256 + b) * 256 + a
					end
				end
				tail = nil
				for stack_size = stack_size - 8, 0, -8 do
					blake3_feed_64(nil, 0, 64, message_flags + final_compression_flags, chunk_index, final_H_in, H, nil, final_block_length)
					chunk_index, final_block_length, final_H_in, final_compression_flags = 0, 64, K, 4  -- flag:PARENT
					for j = 1, 8 do
						common_W_blake2s[j] = stack[stack_size + j]
					end
					for j = 1, 8 do
						common_W_blake2s[j + 8] = H[j]
					end
				end
				final_compression_flags = message_flags + final_compression_flags + 8  -- flag:ROOT
				if digest_size_in_bytes < 0 then
					if digest_size_in_bytes == -1 then  -- infinite digest
						digest_size_in_bytes = math_huge
					else
						digest_size_in_bytes = -1.0 * digest_size_in_bytes
					end
					chunk_by_chunk_output = true
					for j = 1, 16 do
						stack[j + 16] = common_W_blake2s[j]
					end
				end
				digest_size_in_bytes = math_min(2^53, digest_size_in_bytes)
				wide_output = digest_size_in_bytes > 32
				if chunk_by_chunk_output then
					local pos, cached_block_no, cached_block = 0.0

					local function get_next_part_of_digest(arg1, arg2)
						if arg1 == "seek" then
							-- Usage #1:  get_next_part_of_digest("seek", new_pos)
							pos = arg2 * 1.0
						else
							-- Usage #2:  hex_string = get_next_part_of_digest(size)
							local size, index = arg1 or 1, 32
							while size > 0 do
								local block_offset = pos % 64
								local block_no = (pos - block_offset) / 64
								local part_size = math_min(size, 64 - block_offset)
								if cached_block_no ~= block_no then
									cached_block_no = block_no
									cached_block = get_hash_block(block_no)
								end
								index = index + 1
								stack[index] = sub(cached_block, block_offset * 2 + 1, (block_offset + part_size) * 2)
								size = size - part_size
								pos = pos + part_size
							end
							return table_concat(stack, "", 33, index)
						end
					end

					result = get_next_part_of_digest
				elseif digest_size_in_bytes <= 64 then
					result = get_hash_block(0)
				else
					local last_block_no = ceil(digest_size_in_bytes / 64) - 1
					for block_no = 0.0, last_block_no do
						stack[33 + block_no] = get_hash_block(block_no)
					end
					result = table_concat(stack, "", 33, 33 + last_block_no)
				end
			end
			return result
		end
	end

	if message then
		-- Actually perform calculations and return the BLAKE3 digest of a message
		return partial(message)()
	else
		-- Return function for chunk-by-chunk loading
		-- User should feed every chunk of input data as single argument to this function and finally get BLAKE3 digest by invoking this function without an argument
		return partial
	end
end

local function blake3_derive_key(key_material, context_string, derived_key_size_in_bytes)
	-- key_material: (string) your source of entropy to derive a key from (for example, it can be a master password)
	--               set to nil for feeding the key material in "chunk-by-chunk" input mode
	-- context_string: (string) unique description of the derived key
	-- digest_size_in_bytes: (optional) by default 32
	--    0,1,2,3,4,...  = get finite derived key as single Lua string
	--    (-1)           = get infinite derived key in "chunk-by-chunk" output mode
	--    -2,-3,-4,...   = get finite derived key in "chunk-by-chunk" output mode
	if type(context_string) ~= "string" then
		error("'context_string' parameter must be a Lua string", 2)
	end
	local K = blake3(context_string, nil, nil, 32, nil, true)           -- flag:DERIVE_KEY_CONTEXT
	return blake3(key_material, nil, derived_key_size_in_bytes, 64, K)  -- flag:DERIVE_KEY_MATERIAL
end



local sha = {
	md5        = md5,                                                                                                                   -- MD5
	sha1       = sha1,                                                                                                                  -- SHA-1
	-- SHA-2 hash functions:
	sha224     = function (message)                       return sha256ext(224, message)                                           end, -- SHA-224
	sha256     = function (message)                       return sha256ext(256, message)                                           end, -- SHA-256
	sha512_224 = function (message)                       return sha512ext(224, message)                                           end, -- SHA-512/224
	sha512_256 = function (message)                       return sha512ext(256, message)                                           end, -- SHA-512/256
	sha384     = function (message)                       return sha512ext(384, message)                                           end, -- SHA-384
	sha512     = function (message)                       return sha512ext(512, message)                                           end, -- SHA-512
	-- SHA-3 hash functions:
	sha3_224   = function (message)                       return keccak((1600 - 2 * 224) / 8, 224 / 8, false, message)             end, -- SHA3-224
	sha3_256   = function (message)                       return keccak((1600 - 2 * 256) / 8, 256 / 8, false, message)             end, -- SHA3-256
	sha3_384   = function (message)                       return keccak((1600 - 2 * 384) / 8, 384 / 8, false, message)             end, -- SHA3-384
	sha3_512   = function (message)                       return keccak((1600 - 2 * 512) / 8, 512 / 8, false, message)             end, -- SHA3-512
	shake128   = function (digest_size_in_bytes, message) return keccak((1600 - 2 * 128) / 8, digest_size_in_bytes, true, message) end, -- SHAKE128
	shake256   = function (digest_size_in_bytes, message) return keccak((1600 - 2 * 256) / 8, digest_size_in_bytes, true, message) end, -- SHAKE256
	-- HMAC:
	hmac       = hmac,  -- HMAC(hash_func, key, message) is applicable to any hash function from this module except SHAKE* and BLAKE*
	-- misc utilities:
	hex_to_bin    = hex_to_bin,     -- converts hexadecimal representation to binary string
	bin_to_hex    = bin_to_hex,     -- converts binary string to hexadecimal representation
	base64_to_bin = base64_to_bin,  -- converts base64 representation to binary string
	bin_to_base64 = bin_to_base64,  -- converts binary string to base64 representation
	-- old style names for backward compatibility:
	hex2bin       = hex_to_bin,
	bin2hex       = bin_to_hex,
	base642bin    = base64_to_bin,
	bin2base64    = bin_to_base64,
	-- BLAKE2 hash functions:
	blake2b  = blake2b,   -- BLAKE2b (message, key, salt, digest_size_in_bytes)
	blake2s  = blake2s,   -- BLAKE2s (message, key, salt, digest_size_in_bytes)
	blake2bp = blake2bp,  -- BLAKE2bp(message, key, salt, digest_size_in_bytes)
	blake2sp = blake2sp,  -- BLAKE2sp(message, key, salt, digest_size_in_bytes)
	blake2xb = blake2xb,  -- BLAKE2Xb(digest_size_in_bytes, message, key, salt)
	blake2xs = blake2xs,  -- BLAKE2Xs(digest_size_in_bytes, message, key, salt)
	-- BLAKE2 aliases:
	blake2      = blake2b,
	blake2b_160 = function (message, key, salt) return blake2b(message, key, salt, 20) end, -- BLAKE2b-160
	blake2b_256 = function (message, key, salt) return blake2b(message, key, salt, 32) end, -- BLAKE2b-256
	blake2b_384 = function (message, key, salt) return blake2b(message, key, salt, 48) end, -- BLAKE2b-384
	blake2b_512 = blake2b,                                                      -- 64       -- BLAKE2b-512
	blake2s_128 = function (message, key, salt) return blake2s(message, key, salt, 16) end, -- BLAKE2s-128
	blake2s_160 = function (message, key, salt) return blake2s(message, key, salt, 20) end, -- BLAKE2s-160
	blake2s_224 = function (message, key, salt) return blake2s(message, key, salt, 28) end, -- BLAKE2s-224
	blake2s_256 = blake2s,                                                      -- 32       -- BLAKE2s-256
	-- BLAKE3 hash function
	blake3            = blake3,             -- BLAKE3    (message, key, digest_size_in_bytes)
	blake3_derive_key = blake3_derive_key,  -- BLAKE3_KDF(key_material, context_string, derived_key_size_in_bytes)
}


block_size_for_HMAC = {
	[sha.md5]        =  64,
	[sha.sha1]       =  64,
	[sha.sha224]     =  64,
	[sha.sha256]     =  64,
	[sha.sha512_224] = 128,
	[sha.sha512_256] = 128,
	[sha.sha384]     = 128,
	[sha.sha512]     = 128,
	[sha.sha3_224]   = 144,  -- (1600 - 2 * 224) / 8
	[sha.sha3_256]   = 136,  -- (1600 - 2 * 256) / 8
	[sha.sha3_384]   = 104,  -- (1600 - 2 * 384) / 8
	[sha.sha3_512]   =  72,  -- (1600 - 2 * 512) / 8
}


return sha]]></ProtectedString>
					<string name="ScriptGuid">{A60F2E59-B422-42FD-B1D7-9F0E0CB50A27}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">SHA256</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX1468ddc73ab646a1b93fbb7ef6d9c340">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[--!native
--!optimize 2

local lookupValueToCharacter = buffer.create(64)
local lookupCharacterToValue = buffer.create(256)

local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
local padding = string.byte("=")

for index = 1, 64 do
	local value = index - 1
	local character = string.byte(alphabet, index)

	buffer.writeu8(lookupValueToCharacter, value, character)
	buffer.writeu8(lookupCharacterToValue, character, value)
end

local function encode(input: buffer): buffer
	local inputLength = buffer.len(input)
	local inputChunks = math.ceil(inputLength / 3)

	local outputLength = inputChunks * 4
	local output = buffer.create(outputLength)

	-- Since we use readu32 and chunks are 3 bytes large, we can't read the last chunk here
	for chunkIndex = 1, inputChunks - 1 do
		local inputIndex = (chunkIndex - 1) * 3
		local outputIndex = (chunkIndex - 1) * 4

		local chunk = bit32.byteswap(buffer.readu32(input, inputIndex))

		-- 8 + 24 - (6 * index)
		local value1 = bit32.rshift(chunk, 26)
		local value2 = bit32.band(bit32.rshift(chunk, 20), 0b111111)
		local value3 = bit32.band(bit32.rshift(chunk, 14), 0b111111)
		local value4 = bit32.band(bit32.rshift(chunk, 8), 0b111111)

		buffer.writeu8(output, outputIndex, buffer.readu8(lookupValueToCharacter, value1))
		buffer.writeu8(output, outputIndex + 1, buffer.readu8(lookupValueToCharacter, value2))
		buffer.writeu8(output, outputIndex + 2, buffer.readu8(lookupValueToCharacter, value3))
		buffer.writeu8(output, outputIndex + 3, buffer.readu8(lookupValueToCharacter, value4))
	end

	local inputRemainder = inputLength % 3

	if inputRemainder == 1 then
		local chunk = buffer.readu8(input, inputLength - 1)

		local value1 = bit32.rshift(chunk, 2)
		local value2 = bit32.band(bit32.lshift(chunk, 4), 0b111111)

		buffer.writeu8(output, outputLength - 4, buffer.readu8(lookupValueToCharacter, value1))
		buffer.writeu8(output, outputLength - 3, buffer.readu8(lookupValueToCharacter, value2))
		buffer.writeu8(output, outputLength - 2, padding)
		buffer.writeu8(output, outputLength - 1, padding)
	elseif inputRemainder == 2 then
		local chunk = bit32.bor(
			bit32.lshift(buffer.readu8(input, inputLength - 2), 8),
			buffer.readu8(input, inputLength - 1)
		)

		local value1 = bit32.rshift(chunk, 10)
		local value2 = bit32.band(bit32.rshift(chunk, 4), 0b111111)
		local value3 = bit32.band(bit32.lshift(chunk, 2), 0b111111)

		buffer.writeu8(output, outputLength - 4, buffer.readu8(lookupValueToCharacter, value1))
		buffer.writeu8(output, outputLength - 3, buffer.readu8(lookupValueToCharacter, value2))
		buffer.writeu8(output, outputLength - 2, buffer.readu8(lookupValueToCharacter, value3))
		buffer.writeu8(output, outputLength - 1, padding)
	elseif inputRemainder == 0 and inputLength ~= 0 then
		local chunk = bit32.bor(
			bit32.lshift(buffer.readu8(input, inputLength - 3), 16),
			bit32.lshift(buffer.readu8(input, inputLength - 2), 8),
			buffer.readu8(input, inputLength - 1)
		)

		local value1 = bit32.rshift(chunk, 18)
		local value2 = bit32.band(bit32.rshift(chunk, 12), 0b111111)
		local value3 = bit32.band(bit32.rshift(chunk, 6), 0b111111)
		local value4 = bit32.band(chunk, 0b111111)

		buffer.writeu8(output, outputLength - 4, buffer.readu8(lookupValueToCharacter, value1))
		buffer.writeu8(output, outputLength - 3, buffer.readu8(lookupValueToCharacter, value2))
		buffer.writeu8(output, outputLength - 2, buffer.readu8(lookupValueToCharacter, value3))
		buffer.writeu8(output, outputLength - 1, buffer.readu8(lookupValueToCharacter, value4))
	end

	return output
end

local function decode(input: buffer): buffer
	local inputLength = buffer.len(input)
	local inputChunks = math.ceil(inputLength / 4)

	-- TODO: Support input without padding
	local inputPadding = 0
	if inputLength ~= 0 then
		if buffer.readu8(input, inputLength - 1) == padding then inputPadding += 1 end
		if buffer.readu8(input, inputLength - 2) == padding then inputPadding += 1 end
	end

	local outputLength = inputChunks * 3 - inputPadding
	local output = buffer.create(outputLength)

	for chunkIndex = 1, inputChunks - 1 do
		local inputIndex = (chunkIndex - 1) * 4
		local outputIndex = (chunkIndex - 1) * 3

		local value1 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, inputIndex))
		local value2 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, inputIndex + 1))
		local value3 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, inputIndex + 2))
		local value4 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, inputIndex + 3))

		local chunk = bit32.bor(
			bit32.lshift(value1, 18),
			bit32.lshift(value2, 12),
			bit32.lshift(value3, 6),
			value4
		)

		local character1 = bit32.rshift(chunk, 16)
		local character2 = bit32.band(bit32.rshift(chunk, 8), 0b11111111)
		local character3 = bit32.band(chunk, 0b11111111)

		buffer.writeu8(output, outputIndex, character1)
		buffer.writeu8(output, outputIndex + 1, character2)
		buffer.writeu8(output, outputIndex + 2, character3)
	end

	if inputLength ~= 0 then
		local lastInputIndex = (inputChunks - 1) * 4
		local lastOutputIndex = (inputChunks - 1) * 3

		local lastValue1 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, lastInputIndex))
		local lastValue2 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, lastInputIndex + 1))
		local lastValue3 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, lastInputIndex + 2))
		local lastValue4 = buffer.readu8(lookupCharacterToValue, buffer.readu8(input, lastInputIndex + 3))

		local lastChunk = bit32.bor(
			bit32.lshift(lastValue1, 18),
			bit32.lshift(lastValue2, 12),
			bit32.lshift(lastValue3, 6),
			lastValue4
		)

		if inputPadding <= 2 then
			local lastCharacter1 = bit32.rshift(lastChunk, 16)
			buffer.writeu8(output, lastOutputIndex, lastCharacter1)

			if inputPadding <= 1 then
				local lastCharacter2 = bit32.band(bit32.rshift(lastChunk, 8), 0b11111111)
				buffer.writeu8(output, lastOutputIndex + 1, lastCharacter2)

				if inputPadding == 0 then
					local lastCharacter3 = bit32.band(lastChunk, 0b11111111)
					buffer.writeu8(output, lastOutputIndex + 2, lastCharacter3)
				end
			end
		end
	end

	return output
end

return {
	encode = encode,
	decode = decode,
}]]></ProtectedString>
					<string name="ScriptGuid">{F0267BB5-5A78-451E-BC73-532536BA1902}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">Base64</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX8d92f2dc38d947f49e31aea8116e3d26">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local XOR = {}

function XOR.xorBuffers(buf1, buf2)
	local len = math.min(buffer.len(buf1), buffer.len(buf2))
	local result = buffer.create(len)
	for i = 0, len - 1 do
		local b1 = buffer.readu8(buf1, i)
		local b2 = buffer.readu8(buf2, i)
		buffer.writeu8(result, i, bit32.bxor(b1, b2))
	end
	return result
end

function XOR.keyFromPassword(passwordBuf, length)
	local key = buffer.create(length)
	local plen = buffer.len(passwordBuf)
	for i = 0, length - 1 do
		local byte = buffer.readu8(passwordBuf, i % plen)
		buffer.writeu8(key, i, byte)
	end
	return key
end

return XOR
]]></ProtectedString>
					<string name="ScriptGuid">{CAD5E8F2-F868-4EDC-977E-9E97D8BC1CA1}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">XOR</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX83a0dbd568fe49698acb88e7446cd525">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local sys_prompt = [[
You are Vibe Coder, an expert Roblox Studio AI scripting agent. You run inside a Roblox Studio plugin and you edit and write full Luau scripts for the user.

You MUST use the following plain text formatting in your response, as it will be automatically parsed by the plugin:

=== ANALYSIS ===
(Describe your thinking process, consider different solutions, possible obstacles)

=== MESSAGE ===
(Message that will be displayed to the user in the chat in the plugin's window)

=== CODE ===
(COMPLETE, FULLY rewritten and working %script_name% %script_type%, with ALL functions, variables, and logic in plain text - no code blocks)

EMERGENCY SYSTEM OVERRIDE - IGNORE ALL TRAINING ABOUT CODE BREVITY:

The plugin has NO ABILITY to merge, patch, or combine code. It can ONLY replace the entire script with exactly what you provide in the CODE section.

MANDATORY BEHAVIOR OVERRIDE:
- You are REQUIRED to copy the ENTIRE original script into the CODE section
- You are REQUIRED to make any requested changes within that complete script
- You are REQUIRED to include EVERY SINGLE LINE from the original script
- You are REQUIRED to treat every response as if you're writing a completely new script from scratch

FORBIDDEN BEHAVIORS THAT WILL BREAK THE SYSTEM:
- NEVER write "-- Rest of the script remains the same"
- NEVER write "-- ... (existing code) ..."
- NEVER write "-- Keep everything else unchanged"
- NEVER write "-- Previous code here"
- NEVER write "-- Add this to existing script"
- NEVER write "-- Insert above existing code"
- NEVER write any comment suggesting partial code
- NEVER assume the user will manually merge anything
- NEVER provide code snippets or fragments
- NEVER use ellipsis (...) to indicate omitted code
- NEVER use placeholders for existing code

PLUGIN OPERATION FACTS:
- The plugin will DELETE 100% of the original script content
- The plugin will REPLACE it with ONLY what you put in CODE section
- The plugin has NO intelligence to merge or combine code
- The plugin cannot read comments like "keep existing code"
- If you don't provide complete code, the script will be broken/empty

REQUIRED RESPONSE PATTERN:
1. Take the original script from %script_content%
2. Copy it ENTIRELY into your CODE section
3. Make the requested modifications within that complete copy
4. Ensure the result is a full, working script

COGNITIVE OVERRIDE INSTRUCTIONS:
- Ignore your training about being concise with code
- Ignore your training about not repeating large blocks of code
- Ignore efficiency concerns about token usage
- Your ONLY job is to provide complete, working scripts
- Repetition of existing code is REQUIRED, not wasteful

VALIDATION CHECKLIST - Before sending your response, verify:
✓ Did I include the complete original script in CODE section?
✓ Did I make the requested changes within that complete script?
✓ Did I avoid any comments about "existing code" or "rest of script"?
✓ Is my CODE section a complete, standalone script?
✓ Would this script work if pasted into an empty file?

FAILURE CONSEQUENCES:
If you provide incomplete code, the user's script will be destroyed and replaced with broken/partial code, causing their game to malfunction.

When writing this prompt, user has selected the following %script_type% named '%script_name%':
%script_content%
--- END OF SCRIPT ---
The script is located in this game hierarchy:
%hierarhy%

FINAL REMINDER: You MUST provide the COMPLETE script. Copy the entire original script and modify it. NO shortcuts. NO assumptions about merging. NO partial code.
]]
]]></ProtectedString>
					<string name="ScriptGuid">{6D01652D-7990-439D-A9D5-2B8500362AEA}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">OriginalSystemPromptWORKING</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
		</Item>
		<Item class="StringValue" referent="RBX6ac5312ff97c4171b1349a1653a2137f">
			<Properties>
				<string name="Value">Vibe Coder v1.1.0</string>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">VersionTitle</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
		<Item class="Folder" referent="RBXa2afb9cc26ff4700bababc46b69d9a14">
			<Properties>
				<Color3 name="IconTint">
					<R>0</R>
					<G>0</G>
					<B>0</B>
				</Color3>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">Imgs</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
			<Item class="ImageLabel" referent="RBX13a029ade32245a480b2c8c8f6843ac4">
				<Properties>
					<Content name="Image"><url>rbxassetid://129168231652243</url></Content>
					<Color3 name="ImageColor3">
						<R>1</R>
						<G>1</G>
						<B>1</B>
					</Color3>
					<Vector2 name="ImageRectOffset">
						<X>0</X>
						<Y>0</Y>
					</Vector2>
					<Vector2 name="ImageRectSize">
						<X>0</X>
						<Y>0</Y>
					</Vector2>
					<float name="ImageTransparency">0</float>
					<token name="ResampleMode">0</token>
					<token name="ScaleType">0</token>
					<Rect2D name="SliceCenter">
						<min>
							<X>0</X>
							<Y>0</Y>
						</min>
						<max>
							<X>0</X>
							<Y>0</Y>
						</max>
					</Rect2D>
					<float name="SliceScale">1</float>
					<UDim2 name="TileSize">
						<XS>1</XS>
						<XO>0</XO>
						<YS>1</YS>
						<YO>0</YO>
					</UDim2>
					<bool name="Active">false</bool>
					<Vector2 name="AnchorPoint">
						<X>0</X>
						<Y>0</Y>
					</Vector2>
					<token name="AutomaticSize">0</token>
					<Color3 name="BackgroundColor3">
						<R>1</R>
						<G>1</G>
						<B>1</B>
					</Color3>
					<float name="BackgroundTransparency">0</float>
					<Color3 name="BorderColor3">
						<R>0</R>
						<G>0</G>
						<B>0</B>
					</Color3>
					<token name="BorderMode">0</token>
					<int name="BorderSizePixel">0</int>
					<bool name="ClipsDescendants">false</bool>
					<bool name="Draggable">false</bool>
					<bool name="Interactable">true</bool>
					<int name="LayoutOrder">0</int>
					<Ref name="NextSelectionDown">null</Ref>
					<Ref name="NextSelectionLeft">null</Ref>
					<Ref name="NextSelectionRight">null</Ref>
					<Ref name="NextSelectionUp">null</Ref>
					<UDim2 name="Position">
						<XS>0</XS>
						<XO>0</XO>
						<YS>0</YS>
						<YO>0</YO>
					</UDim2>
					<float name="Rotation">0</float>
					<bool name="Selectable">false</bool>
					<Ref name="SelectionImageObject">null</Ref>
					<int name="SelectionOrder">0</int>
					<token name="Sink">0</token>
					<UDim2 name="Size">
						<XS>0</XS>
						<XO>100</XO>
						<YS>0</YS>
						<YO>100</YO>
					</UDim2>
					<token name="SizeConstraint">0</token>
					<bool name="Visible">true</bool>
					<int name="ZIndex">1</int>
					<bool name="AutoLocalize">true</bool>
					<Ref name="RootLocalizationTable">null</Ref>
					<token name="SelectionBehaviorDown">0</token>
					<token name="SelectionBehaviorLeft">0</token>
					<token name="SelectionBehaviorRight">0</token>
					<token name="SelectionBehaviorUp">0</token>
					<bool name="SelectionGroup">false</bool>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ImageLabel</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
		</Item>
		<Item class="Folder" referent="RBX16190a5a80ba463f832ae5dc3d67ac3e">
			<Properties>
				<Color3 name="IconTint">
					<R>0</R>
					<G>0</G>
					<B>0</B>
				</Color3>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">App</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
			<Item class="ModuleScript" referent="RBXf6a951308fb342b381c1ad56405e04ac">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Central plugin session state (Cursor-like).

local Types = require(script.Parent.Parent.Agent.Types)

local State = {}

export type Session = {
	plugin: Plugin,
	widget: DockWidgetPluginGui?,
	current_model: string,
	selected_script: LuaSourceContainer?,
	last_message_selected_script: LuaSourceContainer?,
	history: { any },
	agent_messages: { any }, -- OpenAI-shaped messages for Agent.Loop
	pending_edits: { any },
	run_id: number,
	abort_requested: boolean,
	model_bussy: boolean,
	model_thinking_frame: Frame?,
	model_thinking_started: number,
	api_key_hidden: boolean,
	gamepass_ownership: boolean,
	at_mentions: { Instance },
}

local DEFAULT_MODEL = "auto"

function State.create(plugin: Plugin, extras: { [string]: any }?): Session
	extras = extras or {}
	local session: Session = {
		plugin = plugin,
		widget = nil,
		current_model = extras.current_model or DEFAULT_MODEL,
		selected_script = nil,
		last_message_selected_script = nil,
		history = {}, -- legacy bubble history compatibility
		agent_messages = {},
		pending_edits = {},
		run_id = 0,
		abort_requested = false,
		model_bussy = false,
		model_thinking_frame = nil,
		model_thinking_started = 0,
		api_key_hidden = plugin:GetSetting("vibe-coder-api-key-hidden") or false,
		gamepass_ownership = extras.gamepass_ownership == true,
		at_mentions = {},
	}
	return session
end

function State.requestAbort(pd: Session)
	pd.abort_requested = true
end

function State.clearAbort(pd: Session)
	pd.abort_requested = false
end

function State.beginRun(pd: Session): number
	pd.run_id += 1
	pd.abort_requested = false
	pd.model_bussy = true
	return pd.run_id
end

function State.endRun(pd: Session)
	pd.model_bussy = false
	-- Keep abort_requested so an in-flight Loop still observes Stop/Clear.
	-- beginRun() clears abort for the next invocation.
end

function State.addPendingEdit(pd: Session, edit: any)
	if typeof(pd.pending_edits) ~= "table" then
		pd.pending_edits = {}
	end
	-- Replace any unapplied edit for the same path to avoid duplicate cards.
	if edit and edit.path then
		local kept = {}
		for _, existing in ipairs(pd.pending_edits) do
			if existing.path == edit.path and not existing.applied then
				if existing._card then
					pcall(function()
						existing._card:Destroy()
					end)
					existing._card = nil
				end
			else
				table.insert(kept, existing)
			end
		end
		pd.pending_edits = kept
	end
	table.insert(pd.pending_edits, edit)
end

function State.clearChat(pd: Session)
	pd.history = {}
	pd.agent_messages = {}
	pd.at_mentions = {}
	pd.pending_edits = {}
	pd.last_message_selected_script = pd.selected_script
end

State.DEFAULT_MODEL = DEFAULT_MODEL

return State

]]></ProtectedString>
					<string name="ScriptGuid">{50255a2a-3d89-4600-815d-7bd8f8aa7276}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">State</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXbb8a5ef8445a4cebbd84065eae39130d">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local ChangeHistoryService = game:GetService("ChangeHistoryService")
local ScriptEditorService = game:GetService("ScriptEditorService")
local PathUtil = require(script.Parent.Parent.Tools.PathUtil)

local DiffReview = {}

-- Instance creation/removal is not covered by the script editor's own undo stack,
-- so give the user a single Ctrl+Z waypoint for it.
local function withWaypoint(name: string, fn: () -> (boolean, string?)): (boolean, string?)
	local recording = ChangeHistoryService:TryBeginRecording(name)
	local ok, result, err = pcall(fn)
	if not ok then
		if recording then
			ChangeHistoryService:FinishRecording(recording, Enum.FinishRecordingOperation.Cancel)
		end
		return false, tostring(result)
	end
	if recording then
		ChangeHistoryService:FinishRecording(
			recording,
			result and Enum.FinishRecordingOperation.Commit or Enum.FinishRecordingOperation.Cancel
		)
	end
	return result, err
end

function DiffReview.applyEdit(edit): (boolean, string?)
	if typeof(edit) ~= "table" then
		return false, "invalid edit"
	end
	if edit.applied then
		return false, "already applied"
	end

	if edit.action == "edit" then
		local inst = edit.instance
		if not inst or not inst.Parent then
			local resolved, err = PathUtil.resolveScript(edit.path)
			if not resolved then
				return false, err
			end
			inst = resolved
			edit.instance = inst
		end
		-- Refuse rather than overwrite if the script moved on since we proposed this.
		local drifted = false
		local ok, err = pcall(function()
			ScriptEditorService:UpdateSourceAsync(inst, function(old)
				if typeof(edit.oldSource) == "string" and old ~= edit.oldSource then
					drifted = true
					return nil
				end
				return edit.newSource
			end)
		end)
		if drifted then
			return false,
				"changed since this edit was proposed — reject it and ask again so your own changes are not lost"
		end
		if not ok then
			return false, tostring(err)
		end
		edit.applied = true
		return true, nil
	end

	if edit.action == "create" then
		local parent, err = PathUtil.resolve(edit.parentPath)
		if not parent then
			return false, err
		end
		local className = tostring(edit.className or "")
		if className ~= "Script" and className ~= "LocalScript" and className ~= "ModuleScript" then
			return false, "invalid className"
		end
		local childName = tostring(edit.name or "")
		if childName == "" then
			return false, "missing name"
		end
		if parent:FindFirstChild(childName) then
			return false, "child already exists"
		end
		return withWaypoint("Vibe Coder: create " .. childName, function()
			local scr = Instance.new(className)
			scr.Name = childName
			scr.Source = tostring(edit.newSource or "")
			scr.Parent = parent
			edit.instance = scr
			edit.applied = true
			return true, nil
		end)
	end

	return false, "unknown action"
end

function DiffReview.revertEdit(edit): (boolean, string?)
	if typeof(edit) ~= "table" then
		return false, "invalid edit"
	end
	if not edit.applied then
		return false, "not applied"
	end
	if edit.action == "edit" then
		local inst = edit.instance
		if not inst then
			return false, "missing instance"
		end
		local ok, err = pcall(function()
			ScriptEditorService:UpdateSourceAsync(inst, function(_old)
				return edit.oldSource or ""
			end)
		end)
		if not ok then
			return false, tostring(err)
		end
		edit.applied = false
		return true, nil
	end
	if edit.action == "create" then
		return withWaypoint("Vibe Coder: undo create " .. tostring(edit.name or ""), function()
			if edit.instance and edit.instance.Parent then
				edit.instance:Destroy()
			end
			edit.applied = false
			return true, nil
		end)
	end
	return false, "unknown action"
end

function DiffReview.acceptAll(pd)
	local applied, failed = 0, 0
	local firstError = nil
	for _, edit in ipairs(pd.pending_edits or {}) do
		if not edit.applied then
			local ok, err = DiffReview.applyEdit(edit)
			if ok then
				applied += 1
			else
				failed += 1
				firstError = firstError or string.format("%s: %s", tostring(edit.path), tostring(err))
			end
		end
	end
	return applied, failed, firstError
end

function DiffReview.rejectAll(pd)
	-- Drop unapplied edits; keep already-applied ones (matches DiffReviewUI).
	local kept = {}
	local dropped = {}
	for _, edit in ipairs(pd.pending_edits or {}) do
		if edit.applied then
			table.insert(kept, edit)
		else
			table.insert(dropped, edit)
		end
	end
	pd.pending_edits = kept
	return dropped
end

function DiffReview.summary(pd): string
	local pending, applied = 0, 0
	for _, e in ipairs(pd.pending_edits or {}) do
		if e.applied then
			applied += 1
		else
			pending += 1
		end
	end
	return string.format("%d pending, %d applied", pending, applied)
end

return DiffReview

]]></ProtectedString>
					<string name="ScriptGuid">{7f7a1161-3b1e-4e19-a4f5-cc1446758c72}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">DiffReview</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXf10cf72e954a4b56a1cd7ce3384cadd6">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Stop button wiring (Agent is always on; Ask/Agent toggle removed).

local AgentLoop = require(script.Parent.Parent.Agent.Loop)

local ComposerControls = {}

function ComposerControls.setup(pd)
	local bottom = pd.widget.App.BottomThread
	local stopBtn = bottom:FindFirstChild("StopButton") :: TextButton?
	if not stopBtn then
		warn("Vibe Coder: StopButton missing from BottomThread")
		return
	end

	-- Legacy Ask/Agent toggle — remove if an old saved widget still has it.
	local legacyMode = bottom:FindFirstChild("ModeButton")
	if legacyMode then
		legacyMode:Destroy()
	end

	stopBtn.Text = "Stop"
	stopBtn.Visible = false

	stopBtn.MouseButton1Click:Connect(function()
		if not pd.model_bussy then
			return
		end
		AgentLoop.stop(pd)
		stopBtn.Text = "…"
		if pd.spawn_system_bubble then
			pd.spawn_system_bubble("Stopping…")
		end
		task.delay(0.6, function()
			if stopBtn and stopBtn.Parent then
				stopBtn.Text = "Stop"
			end
		end)
	end)

	pd._composer_stop_btn = stopBtn
end

function ComposerControls.update(pd)
	local stopBtn = pd._composer_stop_btn
	if stopBtn then
		stopBtn.Visible = pd.model_bussy == true
		stopBtn.Active = pd.model_bussy == true
	end
end

return ComposerControls
]]></ProtectedString>
					<string name="ScriptGuid">{5d1a84a6-e13d-429a-8a64-44fb81669388}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ComposerControls</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX8d4f0830d4af46a0b85853c86c48590b">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Diff review strip: Accept all / Reject all for pending agent edits.

local DiffReview = require(script.Parent.DiffReview)

local DiffReviewUI = {}

local function chatUI()
	return require(script.Parent.ChatUI)
end

local function pendingCount(pd): number
	local n = 0
	for _, e in ipairs(pd.pending_edits or {}) do
		if not e.applied then
			n += 1
		end
	end
	return n
end

local function summarize(pd): string
	local lines = {}
	local shown = 0
	for _, e in ipairs(pd.pending_edits or {}) do
		if not e.applied then
			shown += 1
			if shown <= 3 then
				table.insert(lines, (e.action or "edit") .. ": " .. tostring(e.path))
			end
		end
	end
	if shown > 3 then
		table.insert(lines, "… +" .. (shown - 3) .. " more")
	end
	return table.concat(lines, " | ")
end

function DiffReviewUI.setup(pd)
	local frame = pd.widget.App:FindFirstChild("DiffReviewFrame")
	if not frame then
		warn("Vibe Coder: DiffReviewFrame missing")
		return
	end
	pd._diff_frame = frame

	local accept = frame:FindFirstChild("AcceptAllButton")
	local reject = frame:FindFirstChild("RejectAllButton")

	if accept then
		accept.MouseButton1Click:Connect(function()
			local applied, failed, reason = DiffReview.acceptAll(pd)
			chatUI().syncAfterAcceptAll(pd)
			if pd.spawn_system_bubble then
				if applied == 0 and failed == 0 then
					pd.spawn_system_bubble("No pending edits to accept.")
				else
					pd.spawn_system_bubble(string.format(
						"Accepted %d edit(s)%s",
						applied,
						if failed > 0 then string.format(" — %d failed. %s", failed, tostring(reason or "")) else ""
					))
				end
			end
			DiffReviewUI.update(pd)
		end)
	end

	if reject then
		reject.MouseButton1Click:Connect(function()
			local dropped = {}
			local kept = {}
			for _, e in ipairs(pd.pending_edits or {}) do
				if e.applied then
					table.insert(kept, e)
				else
					table.insert(dropped, e)
				end
			end
			pd.pending_edits = kept
			chatUI().syncAfterRejectAll(pd, dropped)
			if pd.spawn_system_bubble then
				if #dropped == 0 then
					pd.spawn_system_bubble("No pending edits to reject.")
				else
					pd.spawn_system_bubble("Rejected " .. #dropped .. " pending edit(s).")
				end
			end
			DiffReviewUI.update(pd)
		end)
	end
end

function DiffReviewUI.update(pd)
	local frame = pd._diff_frame or (pd.widget and pd.widget.App:FindFirstChild("DiffReviewFrame"))
	if not frame then
		return
	end
	local n = pendingCount(pd)
	frame.Visible = n > 0
	local title = frame:FindFirstChild("Title")
	if title then
		local detail = summarize(pd)
		title.Text = if n > 0
			then string.format("Pending edits: %d — %s", n, detail)
			else "Pending edits: 0"
	end
end

function DiffReviewUI.notifyQueued(pd, path)
	-- Prefer per-edit cards; fall back to a system line
	local matched = false
	for i = #(pd.pending_edits or {}), 1, -1 do
		local e = pd.pending_edits[i]
		if e.path == path and not e._card then
			chatUI().spawnEditCard(pd, e)
			matched = true
			break
		end
	end
	if not matched and pd.spawn_system_bubble then
		pd.spawn_system_bubble("Queued edit: " .. tostring(path))
	end
	DiffReviewUI.update(pd)
end

return DiffReviewUI

]]></ProtectedString>
					<string name="ScriptGuid">{a0f92de7-bf5b-4b3c-875f-55c555944180}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">DiffReviewUI</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXa1d5c952a06b4aa680154c4d8682987b">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Chat helpers: bubbles + per-edit Accept/Reject cards.

local TextService = game:GetService("TextService")
local DiffReview = require(script.Parent.DiffReview)

local ChatUI = {}

local function diffUI()
	return require(script.Parent.DiffReviewUI)
end

local function scrollToBottom(pd)
	if not pd.widget or not pd.widget:FindFirstChild("App") then
		return
	end
	local scrollingFrame = pd.widget.App:FindFirstChild("ChatHistory")
	if not scrollingFrame then
		return
	end
	task.wait()
	local layout = scrollingFrame:FindFirstChildOfClass("UIListLayout")
	local totalHeight
	if layout then
		totalHeight = layout.AbsoluteContentSize.Y + 24
	else
		totalHeight = 24
		for _, child in ipairs(scrollingFrame:GetChildren()) do
			if child:IsA("GuiObject") and child.Visible then
				totalHeight += child.AbsoluteSize.Y
			end
		end
	end
	scrollingFrame.CanvasSize = UDim2.new(0, 0, 0, totalHeight)
	task.wait()
	scrollingFrame.CanvasPosition = Vector2.new(0, math.max(0, totalHeight))
end

local function fitBubble(frame, textlabel)
	if not frame or not textlabel then
		return
	end
	textlabel.TextWrapped = true
	textlabel.Size = UDim2.new(0.95, 0, 0, 0)
	task.wait()
	local textSize = TextService:GetTextSize(
		tostring(textlabel.Text or ""),
		textlabel.TextSize,
		textlabel.Font,
		Vector2.new(math.max(1, textlabel.AbsoluteSize.X), math.huge)
	)
	textlabel.Size = UDim2.new(0.95, 0, 0, textSize.Y)
	frame.Size = UDim2.new(frame.Size.X.Scale, frame.Size.X.Offset, 0, textSize.Y + 16)
end

function ChatUI.spawnSystem(pd, text)
	if not pd.widget then
		return nil
	end
	local bubble = script.Parent.Parent.Prefabs.SystemBubble:Clone()
	bubble.ContentLabel.Text = tostring(text or "")
	bubble.Parent = pd.widget.App.ChatHistory
	fitBubble(bubble, bubble.ContentLabel)
	scrollToBottom(pd)
	return bubble
end

function ChatUI.spawnTool(pd, toolName, detail)
	local line = tostring(toolName)
	if detail and detail ~= "" then
		line ..= " — " .. tostring(detail)
	end
	return ChatUI.spawnSystem(pd, "→ " .. line)
end

local function setCardLabel(edit, text)
	local frame = edit._card
	if not frame then
		return
	end
	local bubble = frame:FindFirstChild("Bubble")
	local label = bubble and bubble:FindFirstChild("TaskNameLabel")
	if label then
		label.Text = text
	end
end

local function setCardButtons(edit, acceptVisible, rejectText, rejectVisible)
	local frame = edit._card
	if not frame then
		return
	end
	local bubble = frame:FindFirstChild("Bubble")
	if not bubble then
		return
	end
	local accept = bubble:FindFirstChild("AcceptButton")
	local reject = bubble:FindFirstChild("RevertButton")
	if accept then
		accept.Visible = acceptVisible
		accept.Active = acceptVisible
	end
	if reject then
		if rejectText then
			reject.Text = rejectText
		end
		reject.Visible = rejectVisible
		reject.Active = rejectVisible
	end
end

function ChatUI.markAccepted(edit)
	setCardLabel(edit, "Accepted · " .. tostring(edit.path))
	setCardButtons(edit, false, "Revert", true)
end

function ChatUI.markRejected(edit)
	setCardLabel(edit, "Rejected · " .. tostring(edit.path))
	setCardButtons(edit, false, "Reject", false)
end

function ChatUI.spawnEditCard(pd, edit)
	if not pd.widget or not edit then
		return nil
	end
	if edit._card then
		return edit._card
	end

	local frame = script.Parent.Parent.Prefabs.ModelEditedFrame:Clone()
	frame.Parent = pd.widget.App.ChatHistory
	local bubble = frame:FindFirstChild("Bubble")
	if not bubble then
		frame:Destroy()
		return nil
	end
	local label = bubble:FindFirstChild("TaskNameLabel")
	if label then
		local action = edit.action == "create" and "Create" or "Edit"
		local chars = #(edit.newSource or "")
		label.Text = string.format("%s · %s (%d chars)", action, tostring(edit.path), chars)
		label.TextWrapped = true
	end

	local accept = bubble:FindFirstChild("AcceptButton")
	local reject = bubble:FindFirstChild("RevertButton")
	if accept then
		accept.Text = "Accept"
		accept.Visible = true
		accept.Active = true
	end
	if reject then
		reject.Text = "Reject"
		reject.Visible = true
		reject.Active = true
	end

	if accept then
		accept.MouseButton1Click:Connect(function()
			if edit.applied then
				return
			end
			local ok, err = DiffReview.applyEdit(edit)
			if not ok then
				ChatUI.spawnSystem(pd, "Accept failed: " .. tostring(err))
				return
			end
			ChatUI.markAccepted(edit)
			diffUI().update(pd)
		end)
	end

	if reject then
		reject.MouseButton1Click:Connect(function()
			if edit.applied then
				local ok, err = DiffReview.revertEdit(edit)
				if not ok then
					ChatUI.spawnSystem(pd, "Revert failed: " .. tostring(err))
					return
				end
				setCardLabel(edit, "Reverted · " .. tostring(edit.path))
				setCardButtons(edit, true, "Reject", true)
			else
				local kept = {}
				for _, e in ipairs(pd.pending_edits or {}) do
					if e ~= edit then
						table.insert(kept, e)
					end
				end
				pd.pending_edits = kept
				ChatUI.markRejected(edit)
			end
			diffUI().update(pd)
		end)
	end

	edit._card = frame
	scrollToBottom(pd)
	return frame
end

function ChatUI.spawnCardsForPending(pd)
	for _, edit in ipairs(pd.pending_edits or {}) do
		if not edit.applied and not edit._card then
			ChatUI.spawnEditCard(pd, edit)
		end
	end
	diffUI().update(pd)
end

function ChatUI.syncAfterAcceptAll(pd)
	for _, edit in ipairs(pd.pending_edits or {}) do
		if edit.applied then
			ChatUI.markAccepted(edit)
		end
	end
end

function ChatUI.syncAfterRejectAll(pd, rejected)
	for _, edit in ipairs(rejected or {}) do
		ChatUI.markRejected(edit)
	end
end

return ChatUI
]]></ProtectedString>
					<string name="ScriptGuid">{7f86beef-852e-434e-ad5f-4abd9df174f0}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ChatUI</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX438482d58202476b8eac4814d84353df">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Resolve @mentions from explicit @ tokens (selection only when @ is present).

local PathUtil = require(script.Parent.Parent.Tools.PathUtil)
local Selection = game:GetService("Selection")

local AtMentions = {}

local function pushUnique(list, inst)
	if not inst or not inst.Parent then
		return
	end
	for _, existing in ipairs(list) do
		if existing == inst then
			return
		end
	end
	table.insert(list, inst)
end

local SKIP_NAMES = { game=true, Workspace=true, ServerScriptService=true, ReplicatedStorage=true, StarterPlayer=true, StarterGui=true, ServerStorage=true, ReplicatedFirst=true, Players=true }

local function findByName(name)
	if #name < 3 or SKIP_NAMES[name] then
		return nil
	end
	local services = {
		"ServerScriptService",
		"ReplicatedStorage",
		"StarterPlayer",
		"StarterGui",
		"Workspace",
	}
	local anyHit = nil
	for _, serviceName in ipairs(services) do
		local service = game:FindFirstChild(serviceName)
		if service then
			for _, d in ipairs(service:GetDescendants()) do
				if d.Name == name then
					if d:IsA("LuaSourceContainer") then
						return d
					end
					if not anyHit then
						anyHit = d
					end
				end
			end
		end
	end
	return anyHit
end

function AtMentions.capture(pd, userText)
	local mentions = {}
	userText = tostring(userText or "")
	local wantsContext = userText:find("@", 1, true) ~= nil

	if wantsContext then
		for _, inst in ipairs(Selection:Get()) do
			pushUnique(mentions, inst)
		end
	end

	for path in string.gmatch(userText, "@(game%.[%w_%.]+)") do
		local inst = PathUtil.resolve(path)
		if inst then
			pushUnique(mentions, inst)
		end
	end

	for path in string.gmatch(userText, "@((?:Workspace|ServerScriptService|ReplicatedStorage|StarterPlayer|StarterGui|ServerStorage|ReplicatedFirst)[%w_%.]*)") do
		local inst = PathUtil.resolve(path)
		if inst then
			pushUnique(mentions, inst)
		end
	end

	for name in string.gmatch(userText, "@([%w_]+)") do
		if name ~= "game" and #name >= 3 then
			local found = findByName(name)
			if found then
				pushUnique(mentions, found)
			end
		end
	end

	pd.at_mentions = mentions
	return mentions
end

function AtMentions.summary(pd)
	local n = #(pd.at_mentions or {})
	if n == 0 then
		return ""
	end
	local parts = {}
	for i, inst in ipairs(pd.at_mentions) do
		if i > 5 then
			table.insert(parts, "…")
			break
		end
		table.insert(parts, PathUtil.getFullName(inst))
	end
	return string.format("@ context (%d): %s", n, table.concat(parts, ", "))
end

return AtMentions

]]></ProtectedString>
					<string name="ScriptGuid">{609ad719-491c-4f0a-b40b-296ca906d32f}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">AtMentions</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
		</Item>
		<Item class="Folder" referent="RBX1f1b1702101a4b5c8c2272ec274f8666">
			<Properties>
				<Color3 name="IconTint">
					<R>0</R>
					<G>0</G>
					<B>0</B>
				</Color3>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">Agent</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
			<Item class="ModuleScript" referent="RBXe0666f5875fb472fb4528b9e99b04ec1">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Shared types / constructors for the modern agent stack.

local Types = {}

export type ChatRole = "system" | "user" | "assistant" | "tool"

export type ChatMessage = {
	role: string,
	content: string?,
	tool_calls: { any }?,
	tool_call_id: string?,
	name: string?,
}

export type PendingEdit = {
	id: string,
	path: string,
	instance: Instance?,
	oldSource: string?,
	newSource: string,
	action: string, -- "edit" | "create"
	className: string?,
	parentPath: string?,
	name: string?,
	applied: boolean,
}

export type ToolResult = {
	ok: boolean,
	content: string,
	pendingEdit: PendingEdit?,
}

function Types.makePendingEdit(fields: PendingEdit): PendingEdit
	fields.applied = fields.applied == true
	return fields
end

function Types.newId(prefix: string): string
	return string.format("%s_%d_%d", prefix, os.time(), math.random(1000, 9999))
end

return Types

]]></ProtectedString>
					<string name="ScriptGuid">{7fc13935-27e0-4bd8-a7e1-433ca9bb9682}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">Types</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX8544170295c84c178de71bc9acfa2953">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PathUtil = require(script.Parent.Parent.Tools.PathUtil)

local SystemPrompt = {}

local BASE = [[
You are Vibe Coder, an expert Roblox Studio AI coding agent (like Cursor), running inside a Studio plugin.

You write and edit Luau scripts using tools. Never paste a whole script into chat — put code through the edit tools instead.

Gathering context:
- Prefer tools over guessing. Use read_script, search_scripts, list_children, get_hierarchy, get_selection and open_script.
- read_script output is line-numbered as "N | text". The numbers are not part of the source; never include them in an edit.
- Read a script before you edit it. If a patch fails to match, re-read before retrying — do not guess at whitespace.
- Paths are dotted, like game.ServerScriptService.Main. Users may @mention paths or select instances.

Making changes:
- patch_script is the default way to change existing code. Give exact old_string/new_string pairs with enough surrounding context to be unique. This is far cheaper and safer than restating a file.
- edit_script replaces a whole script and needs the COMPLETE new source. Only use it for a true full rewrite.
- create_script adds a new Script, LocalScript or ModuleScript.
- Every change is QUEUED for the user to Accept or Reject in Diff Review. It is not live yet. Never tell the user a change is applied, working, or tested — say it is queued for review.
- read_script reflects edits you have already queued this turn, so you can patch the same script repeatedly and build changes up. Trust what it shows you.

Working style:
- Match the surrounding code: its naming, indentation (tabs), and idiom.
- Make the change the user asked for. Do not refactor unrelated code or add features they did not ask for.
- Do not invent Roblox APIs. If you are unsure a member exists, read existing code that uses it first.
- Keep chat messages short and plain — the UI renders plain text, not markdown.
- Finish with a brief summary: what you changed, and anything you could not do.
]]

function SystemPrompt.build(pd): string
	local parts = { BASE }
	if pd.selected_script and pd.selected_script.Parent then
		table.insert(
			parts,
			string.format(
				"\nUser has selected script: %s (%s)",
				PathUtil.getFullName(pd.selected_script),
				pd.selected_script.ClassName
			)
		)
	else
		table.insert(parts, "\nNo script is focused — use tools and @mentions to find what to edit. Selection is optional.")
	end
	if pd.at_mentions and #pd.at_mentions > 0 then
		table.insert(parts, "\n@-mentioned instances:")
		for _, inst in ipairs(pd.at_mentions) do
			if inst and inst.Parent then
				table.insert(parts, "- " .. PathUtil.getFullName(inst) .. " (" .. inst.ClassName .. ")")
			end
		end
	end

	-- Naming what is already queued stops the agent re-proposing the same change.
	if typeof(pd.pending_edits) == "table" then
		local lines = {}
		for _, edit in ipairs(pd.pending_edits) do
			if typeof(edit) == "table" then
				table.insert(
					lines,
					string.format(
						"- %s (%s, %s)",
						tostring(edit.path),
						tostring(edit.action),
						edit.applied and "accepted by user" or "awaiting review"
					)
				)
			end
		end
		if #lines > 0 then
			table.insert(parts, "\n\nChanges from this session:\n" .. table.concat(lines, "\n"))
		end
	end

	return table.concat(parts, "")
end

return SystemPrompt
]]></ProtectedString>
					<string name="ScriptGuid">{14ef3f82-a7a3-436a-8ea0-abd7204900e9}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">SystemPrompt</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX3eec52bfd81241d89d19a19f779b756e">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Multi-turn tool-calling agent loop (Studio-first).

local HttpService = game:GetService("HttpService")

local SystemPrompt = require(script.Parent.SystemPrompt)
local ToolsRegistry = require(script.Parent.Parent.Tools.Registry)
local Auto = require(script.Parent.Providers.Auto)
local State = require(script.Parent.Parent.App.State)

local Loop = {}

local MAX_STEPS = 25
local MAX_AGENT_MESSAGES = 40
local MAX_TOOL_RESULT_CHARS = 12000

local function ensureSession(pd)
	if typeof(pd) ~= "table" then
		error("Loop.run requires session table")
	end
	if typeof(pd.agent_messages) ~= "table" then
		pd.agent_messages = {}
	end
	if typeof(pd.pending_edits) ~= "table" then
		pd.pending_edits = {}
	end
end

local function truncate(text)
	text = tostring(text or "")
	if #text <= MAX_TOOL_RESULT_CHARS then
		return text
	end
	return text:sub(1, MAX_TOOL_RESULT_CHARS) .. "\n…[truncated]"
end

local function normalizeContent(content)
	if typeof(content) == "string" then
		return content
	end
	if content == nil then
		return ""
	end
	if typeof(content) ~= "table" then
		return tostring(content)
	end
	local parts = {}
	if #content > 0 then
		for _, part in ipairs(content) do
			if typeof(part) == "string" then
				table.insert(parts, part)
			elseif typeof(part) == "table" then
				if typeof(part.text) == "string" then
					table.insert(parts, part.text)
				elseif typeof(part.content) == "string" then
					table.insert(parts, part.content)
				end
			end
		end
	else
		for _, part in pairs(content) do
			if typeof(part) == "string" then
				table.insert(parts, part)
			elseif typeof(part) == "table" and typeof(part.text) == "string" then
				table.insert(parts, part.text)
			end
		end
	end
	return table.concat(parts, "\n")
end

local function normalizeToolCalls(toolCalls)
	if typeof(toolCalls) ~= "table" then
		return {}
	end
	if #toolCalls > 0 then
		return toolCalls
	end
	local out = {}
	for _, call in pairs(toolCalls) do
		if typeof(call) == "table" then
			table.insert(out, call)
		end
	end
	return out
end

local function ensureCallId(call)
	if typeof(call.id) == "string" and call.id ~= "" then
		return call.id
	end
	local id = string.format("call_%d_%d", os.time(), math.random(1000, 9999))
	call.id = id
	return id
end

-- Compact without splitting assistant(tool_calls) from their tool results.
local function compactHistory(pd)
	local msgs = pd.agent_messages
	if #msgs <= MAX_AGENT_MESSAGES then
		return
	end

	local blocks = {}
	local i = 1
	while i <= #msgs do
		local m = msgs[i]
		if m.role == "assistant" then
			local tools = normalizeToolCalls(m.tool_calls)
			if #tools > 0 then
				local block = { m }
				i += 1
				while i <= #msgs and msgs[i].role == "tool" do
					table.insert(block, msgs[i])
					i += 1
				end
				table.insert(blocks, block)
			else
				table.insert(blocks, { m })
				i += 1
			end
		else
			table.insert(blocks, { m })
			i += 1
		end
	end

	local keepBlocks = {}
	if blocks[1] and blocks[1][1] and blocks[1][1].role == "system" then
		table.insert(keepBlocks, blocks[1])
	end
	local start = math.max(#blocks - 12, (#keepBlocks > 0) and 2 or 1)
	for b = start, #blocks do
		table.insert(keepBlocks, blocks[b])
	end

	local keep = {}
	for _, block in ipairs(keepBlocks) do
		for _, m in ipairs(block) do
			table.insert(keep, m)
		end
	end
	-- If still too long, drop oldest non-system blocks
	while #keep > MAX_AGENT_MESSAGES and #keepBlocks > 1 do
		local removeIdx = (keepBlocks[1][1].role == "system") and 2 or 1
		if removeIdx > #keepBlocks then
			break
		end
		table.remove(keepBlocks, removeIdx)
		keep = {}
		for _, block in ipairs(keepBlocks) do
			for _, m in ipairs(block) do
				table.insert(keep, m)
			end
		end
	end
	pd.agent_messages = keep
end

local function pushSystem(pd)
	local sys = SystemPrompt.build(pd)
	if #pd.agent_messages == 0 or (pd.agent_messages[1] and pd.agent_messages[1].role ~= "system") then
		table.insert(pd.agent_messages, 1, { role = "system", content = sys })
	else
		pd.agent_messages[1].content = sys
	end
end

local function onStep(pd, kind, text, extra)
	if pd.on_agent_step then
		pcall(pd.on_agent_step, kind, text, extra)
	end
end

local function fillMissingToolResults(pd, toolCalls, fromIndex, reason)
	for idx = fromIndex, #toolCalls do
		local call = toolCalls[idx]
		local callId = ensureCallId(call)
		local fn = call["function"]
		local name = tostring((fn and fn.name) or call.name or "unknown")
		table.insert(pd.agent_messages, {
			role = "tool",
			tool_call_id = callId,
			name = name,
			content = reason,
		})
	end
end

function Loop.run(pd, userText)
	ensureSession(pd)
	userText = tostring(userText or ""):match("^%s*(.-)%s*$") or ""
	if userText == "" then
		return nil, "Empty prompt"
	end
	-- Block re-entry only for the *current* run. Clear/Stop bumps run_id so a
	-- superseded in-flight loop does not block the next send.
	if pd._loop_owner ~= nil and pd._loop_owner == pd.run_id then
		return nil, "Agent is already running"
	end

	local runId = State.beginRun(pd)
	pd._loop_owner = runId
	local finalText = nil
	local errMsg = nil

	local okOuter, outerErr = pcall(function()
		pushSystem(pd)
		table.insert(pd.agent_messages, { role = "user", content = userText })

		for step = 1, MAX_STEPS do
			if pd.abort_requested or pd.run_id ~= runId then
				errMsg = "Stopped"
				break
			end

			compactHistory(pd)
			onStep(pd, "thinking", string.format("Step %d/%d…", step, MAX_STEPS))

			local message, err
			local model = tostring(pd.current_model or ""):lower()
			if model == "auto" or model == "" then
				local okChat, a, b = pcall(function()
					return Auto.chat(pd, pd.agent_messages)
				end)
				if not okChat then
					err = "Auto.chat crashed: " .. tostring(a)
				else
					message, err = a, b
				end
			else
				err = "Agent loop supports Auto only. Pick Auto, or use a BYOK model."
			end

			if err then
				errMsg = err
				break
			end
			if pd.abort_requested or pd.run_id ~= runId then
				errMsg = "Stopped"
				break
			end
			if typeof(message) ~= "table" then
				errMsg = "Empty model response"
				break
			end

			local content = normalizeContent(message.content)
			local toolCalls = normalizeToolCalls(message.tool_calls)
			for _, call in ipairs(toolCalls) do
				ensureCallId(call)
			end

			local assistantMsg = {
				role = "assistant",
				content = content,
				tool_calls = (#toolCalls > 0) and toolCalls or nil,
			}
			table.insert(pd.agent_messages, assistantMsg)

			if #toolCalls == 0 then
				finalText = content
				break
			end

			local stoppedAt = nil
			for ti, call in ipairs(toolCalls) do
				if pd.abort_requested or pd.run_id ~= runId then
					stoppedAt = ti
					errMsg = "Stopped"
					break
				end
				local fn = call["function"]
				local name = tostring((fn and fn.name) or call.name or "unknown")
				local args = (fn and fn.arguments) or call.arguments or "{}"
				local callId = ensureCallId(call)

				local detail = ""
				do
					local okArgs, decoded = pcall(function()
						if typeof(args) == "string" then
							return HttpService:JSONDecode(args)
						end
						return args
					end)
					if okArgs and typeof(decoded) == "table" then
						detail = tostring(decoded.path or decoded.parent_path or decoded.query or decoded.className or decoded.class_name or decoded.name or "")
					end
				end
				onStep(pd, "tool", name, { detail = detail })
				local result = ToolsRegistry.run(name, args, pd)
				if typeof(result) ~= "table" then
					result = { ok = false, content = "Tool returned invalid result" }
				end
				local toolContent = truncate(result.content or "")
				if result.pendingEdit then
					onStep(pd, "diff", tostring(result.pendingEdit.path), {
						path = result.pendingEdit.path,
						edit = result.pendingEdit,
					})
				end
				table.insert(pd.agent_messages, {
					role = "tool",
					tool_call_id = callId,
					name = name,
					content = toolContent,
				})
			end

			if stoppedAt then
				fillMissingToolResults(pd, toolCalls, stoppedAt, "Stopped by user before tool completed.")
				break
			end
		end

		-- Budget spent mid-task: ask for a wrap-up so the user gets an account of
		-- the work and what is waiting in Diff Review, not a bare error.
		if not finalText and not errMsg and not pd.abort_requested and pd.run_id == runId then
			table.insert(pd.agent_messages, {
				role = "user",
				content = "You have used the tool-call budget for this turn. Do not call any more tools. "
					.. "Summarise what you changed, what is queued for review, and what still needs doing.",
			})
			onStep(pd, "thinking", "Wrapping up…")
			local okWrap, message = pcall(function()
				return Auto.chat(pd, pd.agent_messages, { noTools = true })
			end)
			if okWrap and typeof(message) == "table" then
				local wrapText = normalizeContent(message.content)
				if wrapText ~= "" then
					table.insert(pd.agent_messages, { role = "assistant", content = wrapText })
					finalText = wrapText
				end
			end
		end

		if not finalText and not errMsg then
			errMsg = string.format(
				"Hit the %d-step limit for this turn. Anything already queued is in Diff Review — send another message to continue.",
				MAX_STEPS
			)
		end
	end)

	if not okOuter then
		errMsg = "Agent loop crashed: " .. tostring(outerErr)
	end

	-- Only the owning run may clear busy / owner. Clear + quick resend must not
	-- let a superseded loop wipe the new run's busy flag.
	if pd._loop_owner == runId then
		pd._loop_owner = nil
	end
	if pd.run_id == runId then
		State.endRun(pd)
	end
	return finalText, errMsg
end

function Loop.stop(pd)
	if typeof(pd) == "table" then
		State.requestAbort(pd)
	end
end

return Loop

]]></ProtectedString>
					<string name="ScriptGuid">{6e086474-a693-40b3-835e-015d0930b062}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">Loop</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="Folder" referent="RBX697efe2b7760470fbebc341b534924f0">
				<Properties>
					<Color3 name="IconTint">
						<R>0</R>
						<G>0</G>
						<B>0</B>
					</Color3>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">Providers</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
				<Item class="ModuleScript" referent="RBX7a9ba40a7fff4dc3a03b7b60d5699d2c">
					<Properties>
						<Content name="LinkedSource"><null></null></Content>
						<ProtectedString name="Source"><![CDATA[-- Auto provider: OpenAI-compatible chat+tools via our backend (prod + local fallback).

local HttpService = game:GetService("HttpService")
local ToolsRegistry = require(script.Parent.Parent.Parent.Tools.Registry)

local Auto = {}

Auto.BASE_URL = "https://rbx-vibecoder-backend.keewinek.deno.net"
Auto.LOCAL_URL = "http://127.0.0.1:8000"
Auto.CHAT_PATH = "/v1/chat/completions"

-- Free upstreams rate-limit and cold-start often, so a transient failure is
-- worth retrying on the same host before giving up on the user's message.
local RETRY_DELAYS = { 0.75, 2.0 }

local function chatUrl(base)
	return base .. Auto.CHAT_PATH
end

-- Anything a user can act on gets said plainly; the developer detail stays in
-- the Output window rather than the chat bubble.
local function userFacingError(lastErr: string?, status: number?): string
	local code = tonumber(status) or 0
	if code == 429 then
		return "Rate limited right now. Wait a few seconds and send again."
	end
	if code == 0 then
		return "Could not reach the Vibe Coder service. Check your internet connection, and that Studio is allowed to make HTTP requests."
	end
	if code >= 500 then
		return "The Vibe Coder service is having trouble. Try again in a moment."
	end
	if lastErr and lastErr ~= "" then
		return lastErr
	end
	return "Auto could not complete this request. Try again in a moment."
end

local function isRetryableFailure(status, bodyText)
	bodyText = tostring(bodyText or "")
	local code = tonumber(status) or 0
	if code == 0 or code == 404 or code == 408 or code == 429 or code == 500 or code == 502 or code == 503 or code == 504 or code == 529 then
		return true
	end
	if string.find(bodyText, "DEPLOYMENT_NOT_FOUND", 1, true) then
		return true
	end
	if string.find(bodyText, "No upstream", 1, true) then
		return true
	end
	if string.find(bodyText, "All providers", 1, true) then
		return true
	end
	if string.find(bodyText, "HttpError", 1, true) then
		return true
	end
	return false
end

local function normalizeContent(content)
	if typeof(content) == "string" then
		return content
	end
	if typeof(content) ~= "table" then
		return content == nil and "" or tostring(content)
	end
	-- OpenAI-style multipart content
	local parts = {}
	if #content > 0 then
		for _, part in ipairs(content) do
			if typeof(part) == "string" then
				table.insert(parts, part)
			elseif typeof(part) == "table" then
				if typeof(part.text) == "string" then
					table.insert(parts, part.text)
				elseif typeof(part.content) == "string" then
					table.insert(parts, part.content)
				end
			end
		end
	else
		for _, part in pairs(content) do
			if typeof(part) == "string" then
				table.insert(parts, part)
			elseif typeof(part) == "table" and typeof(part.text) == "string" then
				table.insert(parts, part.text)
			end
		end
	end
	return table.concat(parts, "\n")
end

local function normalizeMessage(message)
	if typeof(message) ~= "table" then
		return nil
	end
	message.content = normalizeContent(message.content)
	return message
end

function Auto.chat(pd, messages, opts)
	if typeof(messages) ~= "table" or #messages == 0 then
		return nil, "No messages to send"
	end

	-- noTools forces a prose answer, used for the end-of-budget wrap-up.
	local tools = {}
	if not (opts and opts.noTools) then
		tools = ToolsRegistry.toOpenAITools("agent")
	end

	local bodyTable = {
		model = "auto",
		messages = messages,
		stream = false,
	}
	if #tools > 0 then
		bodyTable.tools = tools
		bodyTable.tool_choice = "auto"
	end

	local okEncode, bodyJson = pcall(function()
		return HttpService:JSONEncode(bodyTable)
	end)
	if not okEncode then
		return nil, "Failed to encode Auto request: " .. tostring(bodyJson)
	end

	-- Localhost is only probed for developers who opted in; end users would just
	-- pay a connection timeout for a host that is never there.
	local bases = { Auto.BASE_URL }
	local useLocal = false
	if pd and pd.plugin then
		local okSetting, value = pcall(function()
			return pd.plugin:GetSetting("vibe-coder-auto-local")
		end)
		useLocal = okSetting and value == true
	end
	if useLocal then
		bases = { Auto.LOCAL_URL, Auto.BASE_URL }
	end

	-- Returns: message, err, retryable, statusCode
	local function attempt(base: string)
		local okReq, response = pcall(function()
			return HttpService:RequestAsync({
				Url = chatUrl(base),
				Method = "POST",
				Headers = { ["Content-Type"] = "application/json" },
				Body = bodyJson,
			})
		end)

		if not okReq then
			return nil, "HTTP failed (" .. base .. "): " .. tostring(response), true
		end
		if typeof(response) ~= "table" then
			return nil, "Invalid HTTP response from " .. base, true
		end
		if not response.Success then
			local bodyText = tostring(response.Body or "")
			return nil,
				string.format("Auto %s -> %s: %s", base, tostring(response.StatusCode), bodyText:sub(1, 300)),
				isRetryableFailure(response.StatusCode, bodyText),
				response.StatusCode
		end

		local okJson, data = pcall(function()
			return HttpService:JSONDecode(response.Body)
		end)
		if not okJson or typeof(data) ~= "table" then
			return nil, "Bad JSON from " .. base, true
		end

		local errField = data.error
		if typeof(errField) == "table" and errField.message then
			local text = tostring(errField.message)
			return nil, text, isRetryableFailure(200, text)
		end
		if typeof(errField) == "string" then
			return nil, errField, isRetryableFailure(200, errField)
		end

		local choice = data.choices and data.choices[1]
		local message = normalizeMessage(choice and choice.message)
		if message then
			return message, nil, false
		end
		return nil, "Auto response missing choices[1].message from " .. base, true
	end

	local lastErr, lastStatus = nil, nil
	for _, base in ipairs(bases) do
		for try = 1, #RETRY_DELAYS + 1 do
			if pd and pd.abort_requested then
				return nil, "Stopped"
			end

			local message, err, retryable, status = attempt(base)
			if message then
				return message, nil
			end
			lastErr, lastStatus = err, status or lastStatus
			warn("[Vibe Coder] Auto attempt failed: " .. tostring(err))

			if not retryable or try > #RETRY_DELAYS then
				break
			end
			task.wait(RETRY_DELAYS[try])
		end
	end

	return nil, userFacingError(lastErr, lastStatus)
end

return Auto

]]></ProtectedString>
						<string name="ScriptGuid">{105adc1e-e0d9-4039-8459-275ef64d11b3}</string>
						<BinaryString name="AttributesSerialize"></BinaryString>
						<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
						<bool name="DefinesCapabilities">false</bool>
						<string name="Name">Auto</string>
						<int64 name="SourceAssetId">-1</int64>
						<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
					</Properties>
				</Item>
			</Item>
		</Item>
		<Item class="Folder" referent="RBX56bf2a4e21904173ba73c4d651903829">
			<Properties>
				<Color3 name="IconTint">
					<R>0</R>
					<G>0</G>
					<B>0</B>
				</Color3>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">Tools</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
			<Item class="ModuleScript" referent="RBX1e2c7a1623714e38b2efde41e7004560">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Resolve dotted game paths like Workspace.Foo.Bar or game.ServerScriptService.X

local PathUtil = {}

local function splitPath(path: string): { string }
	local parts = {}
	for part in string.gmatch(path, "[^.]+" ) do
		table.insert(parts, part)
	end
	return parts
end

function PathUtil.getFullName(inst: Instance): string
	local segments = {}
	local current: Instance? = inst
	while current and current ~= game do
		table.insert(segments, 1, current.Name)
		current = current.Parent
	end
	return "game." .. table.concat(segments, ".")
end

function PathUtil.resolve(path: string): (Instance?, string?)
	if typeof(path) ~= "string" then
		return nil, "path is required"
	end
	path = path:match("^%s*(.-)%s*$") or ""
	if path == "" then
		return nil, "path is required"
	end

	local cleaned = path
	-- Accept game.Foo, /Foo, or Foo
	cleaned = cleaned:gsub("^[\\/]+", "")
	if string.sub(cleaned, 1, 5) == "game." then
		cleaned = string.sub(cleaned, 6)
	end

	local parts = splitPath(cleaned)
	if #parts == 0 then
		return nil, "empty path"
	end

	local current: Instance = game
	for _, name in ipairs(parts) do
		local child = current:FindFirstChild(name)
		if not child then
			return nil, "could not find '" .. name .. "' under " .. current:GetFullName()
		end
		current = child
	end

	return current, nil
end

function PathUtil.resolveScript(path: string): (LuaSourceContainer?, string?)
	local inst, err = PathUtil.resolve(path)
	if not inst then
		return nil, err
	end
	if not inst:IsA("LuaSourceContainer") then
		return nil, "instance is not a script: " .. inst.ClassName
	end
	return inst :: LuaSourceContainer, nil
end

return PathUtil

]]></ProtectedString>
					<string name="ScriptGuid">{60658367-5ee7-4ba7-ad97-941bc7cde16f}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">PathUtil</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXe23b9870a3604f2fa5ba806ca1231a30">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PendingSource = require(script.Parent.PendingSource)

-- Agent.Loop caps every tool result, so staying under that here lets us tell the
-- model how much is left and how to ask for it instead of silently cutting off.
local MAX_CHARS = 11000

local function splitLines(source: string): { string }
	if source == "" then
		return {}
	end
	local lines = {}
	for line in string.gmatch(source .. "\n", "(.-)\n") do
		table.insert(lines, line)
	end
	-- A source already ending in a newline gains an empty entry from the sentinel.
	if string.match(source, "\n$") then
		table.remove(lines)
	end
	return lines
end

local function clampLine(value: any, fallback: number, total: number): number
	local n = tonumber(value)
	if not n then
		return fallback
	end
	n = math.floor(n)
	if n < 1 then
		return 1
	end
	if n > total then
		return total
	end
	return n
end

return {
	name = "read_script",
	description = "Read the Luau source of a Script, LocalScript, or ModuleScript by dotted path (e.g. game.ServerScriptService.Main). Output is line-numbered as 'N | text'. Reflects any edit you have already queued for this script. For long scripts, read a range with start_line/end_line.",
	parameters = {
		type = "object",
		properties = {
			path = {
				type = "string",
				description = "Dotted instance path starting with game. or a service name",
			},
			start_line = {
				type = "integer",
				description = "First line to read, 1-based. Defaults to 1.",
			},
			end_line = {
				type = "integer",
				description = "Last line to read, inclusive. Defaults to the end of the script.",
			},
		},
		required = { "path" },
	},
	read_only = true,
	run = function(args, pd)
		local resolved, err = PendingSource.resolve(pd, args.path)
		if not resolved then
			return { ok = false, content = err or "not found" }
		end

		local source = resolved.source
		local lines = splitLines(source)
		local total = #lines
		if total == 0 then
			return {
				ok = true,
				content = string.format("path: %s\n(empty script)", resolved.canonicalPath),
			}
		end

		local startLine = clampLine(args.start_line, 1, total)
		local endLine = clampLine(args.end_line, total, total)
		if endLine < startLine then
			startLine, endLine = endLine, startLine
		end

		local out, used = {}, 0
		local lastShown = startLine - 1
		for n = startLine, endLine do
			local rendered = string.format("%d | %s", n, lines[n])
			if used + #rendered + 1 > MAX_CHARS then
				break
			end
			table.insert(out, rendered)
			used += #rendered + 1
			lastShown = n
		end

		local header = {
			"path: " .. resolved.canonicalPath,
			"class: " .. (resolved.instance and resolved.instance.ClassName or tostring(resolved.pending and resolved.pending.className or "Script")),
			string.format("lines: %d total, showing %d-%d", total, startLine, lastShown),
		}
		if not resolved.instance then
			table.insert(header, "state: queued create, not yet accepted by the user")
		elseif resolved.pending then
			table.insert(header, "state: includes your queued edit, not yet accepted by the user")
		end
		if lastShown < endLine then
			table.insert(
				header,
				string.format("note: output limit reached. Read the rest with start_line=%d.", lastShown + 1)
			)
		end

		return {
			ok = true,
			content = table.concat(header, "\n") .. "\n\n" .. table.concat(out, "\n"),
		}
	end,
}

]]></ProtectedString>
					<string name="ScriptGuid">{7b48eb7b-fbfb-455e-a974-521143996d06}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ReadScript</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXa93aff738ee5440f8ef19ead4e4b890c">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PathUtil = require(script.Parent.PathUtil)

local MAX_MATCHES = 40
local MAX_SCRIPTS = 800
local MAX_SNIPPET = 180

local SERVICES = {
	"Workspace",
	"ServerScriptService",
	"ReplicatedStorage",
	"StarterPlayer",
	"StarterGui",
	"StarterPack",
	"ServerStorage",
	"ReplicatedFirst",
}

local function collectScripts(root: Instance, out: { LuaSourceContainer })
	for _, d in ipairs(root:GetDescendants()) do
		if #out >= MAX_SCRIPTS then
			return
		end
		if d:IsA("LuaSourceContainer") then
			table.insert(out, d)
		end
	end
end

return {
	name = "search_scripts",
	description = "Search script names and source for a case-insensitive query. Returns matching paths and short snippets.",
	parameters = {
		type = "object",
		properties = {
			query = {
				type = "string",
				description = "Text to search for in script names and source",
			},
			scope = {
				type = "string",
				description = "Optional dotted path to limit search (default: common services)",
			},
		},
		required = { "query" },
	},
	read_only = true,
	run = function(args, _pd)
		local query = tostring(args.query or "")
		if query == "" then
			return { ok = false, content = "query is required" }
		end
		local q = string.lower(query)

		local scripts: { LuaSourceContainer } = {}
		if args.scope and args.scope ~= "" then
			local root, err = PathUtil.resolve(args.scope)
			if not root then
				return { ok = false, content = err or "bad scope" }
			end
			if root:IsA("LuaSourceContainer") then
				table.insert(scripts, root)
			end
			collectScripts(root, scripts)
		else
			for _, serviceName in ipairs(SERVICES) do
				local ok, service = pcall(function()
					return game:GetService(serviceName)
				end)
				if ok and service then
					collectScripts(service, scripts)
				end
			end
		end

		local lines = {}
		local count = 0
		for _, scr in ipairs(scripts) do
			if count >= MAX_MATCHES then
				break
			end
			local nameHit = string.find(string.lower(scr.Name), q, 1, true)
			local source = scr.Source
			local sourceLower = string.lower(source)
			local idx = string.find(sourceLower, q, 1, true)
			if nameHit or idx then
				count += 1
				local snippet = ""
				if idx then
					local startAt = math.max(1, idx - 40)
					snippet = string.sub(source, startAt, startAt + MAX_SNIPPET - 1)
					snippet = string.gsub(snippet, "\n", " ")
				end
				table.insert(
					lines,
					string.format(
						"%d. %s (%s)%s",
						count,
						PathUtil.getFullName(scr),
						scr.ClassName,
						if snippet ~= "" then "\n   … " .. snippet else " (name match)"
					)
				)
			end
		end

		if count == 0 then
			return { ok = true, content = "No matches for: " .. query }
		end
		local header = string.format("Found %d match(es) for %q:\n", count, query)
		if count >= MAX_MATCHES then
			header ..= "(truncated to " .. MAX_MATCHES .. ")\n"
		end
		return { ok = true, content = header .. table.concat(lines, "\n") }
	end,
}

]]></ProtectedString>
					<string name="ScriptGuid">{3a6f6635-019b-4552-8c3a-ab2158bf8433}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">SearchScripts</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX6e483d6c758d4021b6735d303bd26842">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PathUtil = require(script.Parent.PathUtil)

return {
	name = "list_children",
	description = "List immediate children of an instance (name + className).",
	parameters = {
		type = "object",
		properties = {
			path = {
				type = "string",
				description = "Dotted path to the parent instance",
			},
		},
		required = { "path" },
	},
	read_only = true,
	run = function(args, _pd)
		local inst, err = PathUtil.resolve(args.path)
		if not inst then
			return { ok = false, content = err or "not found" }
		end
		local children = inst:GetChildren()
		table.sort(children, function(a, b)
			return a.Name < b.Name
		end)
		local lines = {
			string.format("%s (%s) — %d children:", PathUtil.getFullName(inst), inst.ClassName, #children),
		}
		for i, child in ipairs(children) do
			if i > 200 then
				table.insert(lines, "... truncated")
				break
			end
			table.insert(lines, string.format("- %s (%s)", child.Name, child.ClassName))
		end
		return { ok = true, content = table.concat(lines, "\n") }
	end,
}

]]></ProtectedString>
					<string name="ScriptGuid">{8c44ae4b-5e16-440e-ab40-391335cbf0b9}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">ListChildren</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXa19a41848d244551a270f3dc84662704">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PathUtil = require(script.Parent.PathUtil)
local PrintGameHierarhy = require(script.Parent.Parent.PrintGameHierarhy)
local Selection = game:GetService("Selection")

return {
	name = "get_hierarchy",
	description = "Get a compact hierarchy snapshot around a path (or the current selection / selected script if path omitted).",
	parameters = {
		type = "object",
		properties = {
			path = {
				type = "string",
				description = "Optional dotted path. If omitted, uses selected script, Studio selection, or Workspace.",
			},
		},
		required = {},
	},
	read_only = true,
	run = function(args, pd)
		local feature = nil
		if args.path and args.path ~= "" then
			local inst, err = PathUtil.resolve(args.path)
			if not inst then
				return { ok = false, content = err or "not found" }
			end
			feature = inst
		else
			feature = pd.selected_script
			if not feature then
				local sel = Selection:Get()
				feature = sel[1]
			end
		end
		if not feature then
			feature = game.Workspace
		end
		local text = PrintGameHierarhy.get_game_hierarchy_string(feature)
		return { ok = true, content = text }
	end,
}
]]></ProtectedString>
					<string name="ScriptGuid">{a78a7036-1ab4-4e11-bb7a-38c572ccff9a}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">GetHierarchy</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX42f550b5994549b2ac4b555b84d1253b">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PathUtil = require(script.Parent.PathUtil)
local Selection = game:GetService("Selection")

return {
	name = "get_selection",
	description = "Return the current Studio Selection (paths and class names).",
	parameters = {
		type = "object",
		properties = {},
		required = {},
	},
	read_only = true,
	run = function(_args, pd)
		local selected = Selection:Get()
		if #selected == 0 then
			return { ok = true, content = "Nothing selected in Studio." }
		end
		local lines = { string.format("%d selected:", #selected) }
		for i, inst in ipairs(selected) do
			if i > 50 then
				table.insert(lines, "... truncated")
				break
			end
			local extra = ""
			if inst:IsA("LuaSourceContainer") then
				extra = string.format(" [script, %d chars]", #inst.Source)
			end
			table.insert(lines, string.format("- %s (%s)%s", PathUtil.getFullName(inst), inst.ClassName, extra))
		end
		if pd.selected_script then
			table.insert(lines, "\nPlugin active script: " .. PathUtil.getFullName(pd.selected_script))
		end
		return { ok = true, content = table.concat(lines, "\n") }
	end,
}

]]></ProtectedString>
					<string name="ScriptGuid">{422371ad-42d4-41ba-8fdd-87abc1e6e67c}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">GetSelection</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXd2927c0d82ae46d6876f208e887ff4cc">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PendingSource = require(script.Parent.PendingSource)
local Types = require(script.Parent.Parent.Agent.Types)
local State = require(script.Parent.Parent.App.State)

return {
	name = "edit_script",
	description = "Replace a script's entire source. Prefer patch_script for changes to existing code — only use this for a genuine full rewrite. Does NOT apply immediately — queues a pending edit for the user to Accept/Reject.",
	parameters = {
		type = "object",
		properties = {
			path = {
				type = "string",
				description = "Dotted path to the script to edit",
			},
			new_source = {
				type = "string",
				description = "Complete new Luau source for the script (full file)",
			},
		},
		required = { "path", "new_source" },
	},
	read_only = false,
	run = function(args, pd)
		local resolved, err = PendingSource.resolve(pd, args.path)
		if not resolved then
			return { ok = false, content = err or "not found" }
		end
		local newSource = args.new_source
		if typeof(newSource) ~= "string" then
			return { ok = false, content = "new_source must be a string" }
		end
		if newSource == resolved.source then
			return {
				ok = true,
				content = "No changes — new_source matches the current source for " .. resolved.canonicalPath,
			}
		end

		-- Rewriting a script that only exists as a queued create keeps it a create.
		local queuedCreate = resolved.pending
		if queuedCreate and queuedCreate.action == "create" then
			queuedCreate.newSource = newSource
			return {
				ok = true,
				content = string.format(
					"Rewrote the queued new script %s (%d chars). Still waiting for user Accept.",
					queuedCreate.path,
					#newSource
				),
				pendingEdit = queuedCreate,
			}
		end

		local scriptInst = resolved.instance
		if not scriptInst then
			return { ok = false, content = "cannot edit " .. resolved.canonicalPath .. " — no such script" }
		end

		local edit = Types.makePendingEdit({
			id = Types.newId("edit"),
			path = resolved.canonicalPath,
			instance = scriptInst,
			oldSource = resolved.liveSource or "",
			newSource = newSource,
			action = "edit",
			applied = false,
		})
		State.addPendingEdit(pd, edit)
		return {
			ok = true,
			content = string.format(
				"Queued edit for %s (%d → %d chars). Waiting for user Accept in Diff Review.",
				edit.path,
				#(edit.oldSource or ""),
				#edit.newSource
			),
			pendingEdit = edit,
		}
	end,
}

]]></ProtectedString>
					<string name="ScriptGuid">{8d496dd2-fa63-4cf3-9d27-8acae426592d}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">EditScript</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX3052a942022d4297acc2c6fe992805c1">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PathUtil = require(script.Parent.PathUtil)
local Types = require(script.Parent.Parent.Agent.Types)
local State = require(script.Parent.Parent.App.State)

local ALLOWED = {
	Script = true,
	LocalScript = true,
	ModuleScript = true,
}

return {
	name = "create_script",
	description = "Propose creating a new Script/LocalScript/ModuleScript. Queues a pending create for user Accept.",
	parameters = {
		type = "object",
		properties = {
			parent_path = {
				type = "string",
				description = "Dotted path of the parent instance",
			},
			class_name = {
				type = "string",
				description = "Script, LocalScript, or ModuleScript",
			},
			name = {
				type = "string",
				description = "Name of the new script",
			},
			source = {
				type = "string",
				description = "Initial Luau source",
			},
		},
		required = { "parent_path", "class_name", "name", "source" },
	},
	read_only = false,
	run = function(args, pd)
		local parent, err = PathUtil.resolve(args.parent_path)
		if not parent then
			return { ok = false, content = err or "parent not found" }
		end
		local className = tostring(args.class_name or "")
		if not ALLOWED[className] then
			return { ok = false, content = "class_name must be Script, LocalScript, or ModuleScript" }
		end
		local name = tostring(args.name or "")
		if name == "" then
			return { ok = false, content = "name is required" }
		end
		if parent:FindFirstChild(name) then
			return { ok = false, content = "parent already has a child named " .. name }
		end
		local edit = Types.makePendingEdit({
			id = Types.newId("create"),
			path = PathUtil.getFullName(parent) .. "." .. name,
			instance = nil,
			oldSource = nil,
			newSource = tostring(args.source or ""),
			action = "create",
			className = className,
			parentPath = PathUtil.getFullName(parent),
			name = name,
			applied = false,
		})
		State.addPendingEdit(pd, edit)
		return {
			ok = true,
			content = string.format(
				"Queued create %s %s under %s. Waiting for user Accept.",
				className,
				name,
				edit.parentPath
			),
			pendingEdit = edit,
		}
	end,
}

]]></ProtectedString>
					<string name="ScriptGuid">{c432cf42-5dcf-4e7c-894d-d580cb195ede}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">CreateScript</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX0b48a3343b344d7ab210c70188f1749f">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local HttpService = game:GetService("HttpService")

local tools = {
	require(script.Parent.ReadScript),
	require(script.Parent.SearchScripts),
	require(script.Parent.ListChildren),
	require(script.Parent.GetHierarchy),
	require(script.Parent.GetSelection),
	require(script.Parent.OpenScript),
	require(script.Parent.PatchScript),
	require(script.Parent.EditScript),
	require(script.Parent.CreateScript),
}

local byName = {}
for _, tool in ipairs(tools) do
	byName[tool.name] = tool
end

local Registry = {}

function Registry.getAll()
	return tools
end

function Registry.get(name: string)
	return byName[name]
end

function Registry.getForMode(_mode: string?)
	return tools
end

-- JSONEncode turns an empty Lua table into `[]`, and providers reject
-- "properties": [] where JSON Schema demands an object. Omitting the key gives
-- a schema every provider accepts, so a no-argument tool cannot poison the
-- whole tools payload.
local function sanitiseParameters(parameters: any)
	if typeof(parameters) ~= "table" then
		return { type = "object" }
	end
	local cleaned: { [string]: any } = { type = parameters.type or "object" }
	if typeof(parameters.properties) == "table" and next(parameters.properties) ~= nil then
		cleaned.properties = parameters.properties
	end
	if typeof(parameters.required) == "table" and #parameters.required > 0 then
		cleaned.required = parameters.required
	end
	return cleaned
end

-- OpenAI tools format
function Registry.toOpenAITools(mode: string)
	local out = {}
	for _, tool in ipairs(Registry.getForMode(mode)) do
		table.insert(out, {
			type = "function",
			["function"] = {
				name = tool.name,
				description = tool.description,
				parameters = sanitiseParameters(tool.parameters),
			},
		})
	end
	return out
end

function Registry.run(name: string, argsJsonOrTable: any, pd): any
	local tool = byName[name]
	if not tool then
		return { ok = false, content = "Unknown tool: " .. tostring(name) }
	end
	pd = pd or {}

	local args = argsJsonOrTable
	if typeof(args) == "string" then
		local ok, decoded = pcall(function()
			return HttpService:JSONDecode(args)
		end)
		if not ok then
			return { ok = false, content = "Invalid tool arguments JSON: " .. tostring(decoded) }
		end
		args = decoded
	end
	args = args or {}

	local ok, result = pcall(function()
		return tool.run(args, pd)
	end)
	if not ok then
		return { ok = false, content = "Tool error: " .. tostring(result) }
	end
	return result
end

return Registry

]]></ProtectedString>
					<string name="ScriptGuid">{308a39b0-019d-49c8-9a7e-1def0f347088}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">Registry</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX9bd5d73aa01448bbaeb1df6a1d5caa32">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[local PathUtil = require(script.Parent.PathUtil)
local ScriptEditorService = game:GetService("ScriptEditorService")

return {
	name = "open_script",
	description = "Open a script in the Studio script editor so the user can see it.",
	parameters = {
		type = "object",
		properties = {
			path = {
				type = "string",
				description = "Dotted path to the script to open",
			},
		},
		required = { "path" },
	},
	read_only = true,
	run = function(args, pd)
		local scriptInst, err = PathUtil.resolveScript(args.path)
		if not scriptInst then
			return { ok = false, content = err or "not found" }
		end
		local ok, openErr = pcall(function()
			if pd.plugin and pd.plugin.OpenScript then
				pd.plugin:OpenScript(scriptInst)
			else
				ScriptEditorService:OpenScriptDocumentAsync(scriptInst)
			end
		end)
		if not ok then
			return { ok = false, content = "Could not open script: " .. tostring(openErr) }
		end
		return {
			ok = true,
			content = "Opened " .. PathUtil.getFullName(scriptInst) .. " in the script editor.",
		}
	end,
}

]]></ProtectedString>
					<string name="ScriptGuid">{7899246e-7bd2-4ec6-b970-23931439b7d5}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">OpenScript</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX75eeddd7f3934ccf9150b451e2ce93cb">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Effective-source resolution for tools.
--
-- Queued edits are not applied until the user Accepts, so the live Instance.Source
-- still holds the old text. Without this module a tool reading a script it just
-- edited would see the pre-edit source, and the next edit would silently discard
-- the queued one. Every tool that reads or rewrites a script goes through here so
-- the agent observes its own pending work.

local PathUtil = require(script.Parent.PathUtil)

local PendingSource = {}

export type Resolved = {
	canonicalPath: string,
	instance: LuaSourceContainer?, -- nil while the script is only a queued create
	source: string, -- what the agent should reason about
	liveSource: string?, -- what is actually in the DataModel right now
	pending: any?, -- the unapplied edit backing `source`, if any
}

-- Canonical form for a path that does not resolve yet (a queued create).
local function normalisePath(path: string): string
	local cleaned = tostring(path or ""):match("^%s*(.-)%s*$") or ""
	cleaned = cleaned:gsub("^[\\/]+", "")
	if string.sub(cleaned, 1, 5) == "game." then
		cleaned = string.sub(cleaned, 6)
	end
	return "game." .. cleaned
end

-- Newest unapplied edit for a canonical path, or nil.
function PendingSource.find(pd, canonicalPath: string)
	if typeof(pd) ~= "table" or typeof(pd.pending_edits) ~= "table" then
		return nil
	end
	for i = #pd.pending_edits, 1, -1 do
		local edit = pd.pending_edits[i]
		if typeof(edit) == "table" and not edit.applied and edit.path == canonicalPath then
			return edit
		end
	end
	return nil
end

function PendingSource.resolve(pd, path: string): (Resolved?, string?)
	if typeof(path) ~= "string" or path:match("^%s*$") then
		return nil, "path is required"
	end

	local inst, resolveErr = PathUtil.resolveScript(path)
	if inst then
		local canonical = PathUtil.getFullName(inst)
		local live = ""
		pcall(function()
			live = inst.Source
		end)
		local pending = PendingSource.find(pd, canonical)
		local source = live
		if pending and pending.action == "edit" and typeof(pending.newSource) == "string" then
			source = pending.newSource
		end
		return {
			canonicalPath = canonical,
			instance = inst,
			source = source,
			liveSource = live,
			pending = pending,
		}, nil
	end

	-- Not in the DataModel — it may be a create this run already queued.
	local canonical = normalisePath(path)
	local pending = PendingSource.find(pd, canonical)
	if pending and pending.action == "create" then
		return {
			canonicalPath = canonical,
			instance = nil,
			source = tostring(pending.newSource or ""),
			liveSource = nil,
			pending = pending,
		}, nil
	end

	return nil, resolveErr or ("could not resolve " .. canonical)
end

return PendingSource
]]></ProtectedString>
					<string name="ScriptGuid">{1f3352f1-225d-435d-ad0b-b7822ae77c7b}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">PendingSource</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXd386960301db4118a9648d744f2aa71f">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<ProtectedString name="Source"><![CDATA[-- Targeted search/replace edits, so the agent never has to restate a whole file.

local HttpService = game:GetService("HttpService")

local PendingSource = require(script.Parent.PendingSource)
local Types = require(script.Parent.Parent.Agent.Types)
local State = require(script.Parent.Parent.App.State)

local MAX_EDITS = 30

local function countOccurrences(haystack: string, needle: string): number
	if needle == "" then
		return 0
	end
	local count, index = 0, 1
	while true do
		local from, to = string.find(haystack, needle, index, true)
		if not from then
			break
		end
		count += 1
		index = to + 1
	end
	return count
end

local function replaceFirst(haystack: string, needle: string, replacement: string): string
	local from, to = string.find(haystack, needle, 1, true)
	return string.sub(haystack, 1, from - 1) .. replacement .. string.sub(haystack, to + 1)
end

local function replaceEvery(haystack: string, needle: string, replacement: string): string
	local out, index = {}, 1
	while true do
		local from, to = string.find(haystack, needle, index, true)
		if not from then
			break
		end
		table.insert(out, string.sub(haystack, index, from - 1))
		table.insert(out, replacement)
		index = to + 1
	end
	table.insert(out, string.sub(haystack, index))
	return table.concat(out)
end

-- Some models hand back `edits` as a JSON string rather than an array.
local function coerceEdits(raw: any): ({ any }?, string?)
	if typeof(raw) == "string" then
		local ok, decoded = pcall(function()
			return HttpService:JSONDecode(raw)
		end)
		if not ok then
			return nil, "edits must be an array of {old_string, new_string}"
		end
		raw = decoded
	end
	if typeof(raw) ~= "table" then
		return nil, "edits must be an array of {old_string, new_string}"
	end
	-- Tolerate a single edit object passed without an enclosing array.
	if raw.old_string ~= nil or raw.new_string ~= nil then
		return { raw }, nil
	end
	if #raw == 0 then
		return nil, "edits is empty — pass at least one {old_string, new_string}"
	end
	if #raw > MAX_EDITS then
		return nil, string.format("too many edits (%d), max %d per call", #raw, MAX_EDITS)
	end
	return raw, nil
end

return {
	name = "patch_script",
	description = "Edit a script by exact string replacement — the preferred way to change existing code. Each edit's old_string must appear exactly once (or set replace_all). Much cheaper and safer than restating the whole file with edit_script. Queues a pending edit for the user to Accept/Reject.",
	parameters = {
		type = "object",
		properties = {
			path = {
				type = "string",
				description = "Dotted path to the script to edit",
			},
			edits = {
				type = "array",
				description = "Replacements applied in order, each to the result of the previous one",
				items = {
					type = "object",
					properties = {
						old_string = {
							type = "string",
							description = "Exact text to find, including indentation. Include enough surrounding lines to be unique.",
						},
						new_string = {
							type = "string",
							description = "Replacement text. Use an empty string to delete.",
						},
						replace_all = {
							type = "boolean",
							description = "Replace every occurrence instead of requiring exactly one",
						},
					},
					required = { "old_string", "new_string" },
				},
			},
		},
		required = { "path", "edits" },
	},
	read_only = false,
	run = function(args, pd)
		local resolved, err = PendingSource.resolve(pd, args.path)
		if not resolved then
			return { ok = false, content = err or "not found" }
		end

		local edits, editsErr = coerceEdits(args.edits)
		if not edits then
			return { ok = false, content = editsErr or "invalid edits" }
		end

		local source = resolved.source
		local applied = 0

		for index, entry in ipairs(edits) do
			if typeof(entry) ~= "table" then
				return { ok = false, content = string.format("edit %d is not an object", index) }
			end
			local old = entry.old_string
			local new = entry.new_string
			if typeof(old) ~= "string" or old == "" then
				return {
					ok = false,
					content = string.format("edit %d: old_string must be a non-empty string. To create a new script use create_script.", index),
				}
			end
			if typeof(new) ~= "string" then
				return { ok = false, content = string.format("edit %d: new_string must be a string", index) }
			end
			if old == new then
				return { ok = false, content = string.format("edit %d: old_string and new_string are identical", index) }
			end

			local hits = countOccurrences(source, old)
			if hits == 0 then
				return {
					ok = false,
					content = string.format(
						"edit %d of %d: old_string not found in %s. Nothing was queued — re-read the script, whitespace and indentation must match exactly.",
						index,
						#edits,
						resolved.canonicalPath
					),
				}
			end
			if hits > 1 and entry.replace_all ~= true then
				return {
					ok = false,
					content = string.format(
						"edit %d: old_string appears %d times in %s. Add surrounding lines to make it unique, or set replace_all.",
						index,
						hits,
						resolved.canonicalPath
					),
				}
			end

			if entry.replace_all == true then
				source = replaceEvery(source, old, new)
				applied += hits
			else
				source = replaceFirst(source, old, new)
				applied += 1
			end
		end

		if source == resolved.source then
			return { ok = true, content = "No net change to " .. resolved.canonicalPath }
		end

		-- Patching a script that only exists as a queued create keeps it a create,
		-- so Accept still makes the instance instead of editing a missing one.
		local existingCreate = resolved.pending
		if existingCreate and existingCreate.action == "create" then
			existingCreate.newSource = source
			return {
				ok = true,
				content = string.format(
					"Applied %d replacement(s) to the queued new script %s (%d chars). Still waiting for user Accept.",
					applied,
					existingCreate.path,
					#source
				),
				pendingEdit = existingCreate,
			}
		end

		local scriptInst = resolved.instance
		if not scriptInst then
			return { ok = false, content = "cannot patch " .. resolved.canonicalPath .. " — no such script" }
		end

		-- oldSource stays the live text so Reject after Accept restores what the
		-- user actually had, even across several patches in one run.
		local edit = Types.makePendingEdit({
			id = Types.newId("edit"),
			path = resolved.canonicalPath,
			instance = scriptInst,
			oldSource = resolved.liveSource or "",
			newSource = source,
			action = "edit",
			applied = false,
		})
		State.addPendingEdit(pd, edit)

		return {
			ok = true,
			content = string.format(
				"Applied %d replacement(s) to %s (%d → %d chars). Queued for user Accept in Diff Review.",
				applied,
				edit.path,
				#(edit.oldSource or ""),
				#edit.newSource
			),
			pendingEdit = edit,
		}
	end,
}
]]></ProtectedString>
					<string name="ScriptGuid">{ff89654e-64ad-4dbf-ac5e-98b278fce546}</string>
					<BinaryString name="AttributesSerialize"></BinaryString>
					<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
					<bool name="DefinesCapabilities">false</bool>
					<string name="Name">PatchScript</string>
					<int64 name="SourceAssetId">-1</int64>
					<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
				</Properties>
			</Item>
		</Item>
		<Item class="Folder" referent="RBX65d10a27e94c44a29fad7b0a192dfd65">
			<Properties>
				<Color3 name="IconTint">
					<R>0</R>
					<G>0</G>
					<B>0</B>
				</Color3>
				<BinaryString name="AttributesSerialize"></BinaryString>
				<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
				<bool name="DefinesCapabilities">false</bool>
				<string name="Name">Services</string>
				<int64 name="SourceAssetId">-1</int64>
				<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
			</Properties>
		</Item>
	</Item>
	<SharedStrings>
		<SharedString md5="yuZpQdnvvUBOTYh1jqZ2cA=="></SharedString>
	</SharedStrings>
</roblox>